diff --git a/doc/src/omake-options.tex b/doc/src/omake-options.tex index f062300..7c6eb6c 100644 --- a/doc/src/omake-options.tex +++ b/doc/src/omake-options.tex @@ -98,6 +98,24 @@ \section{Output control} Make \OMake{} very verbose. This option is equivalent to \verb+--no-S --print-status --print-exit VERBOSE=true+ +\option{--output-direct} \verb+--output-direct+ + +For jobs executed on the local machine leave \verb+stdout+ and \verb+stderr+ alone; do not redirect +them as \OMake{} normally does. This is useful for commands that test for or need a TTY, like for +example pagers and (text-)browsers. + +Example: +\begin{verbatim} +section + OMakeFlags(--output-direct) + + .PHONY: view-doc + view-doc: index.html + w3m -o confirm_qq=false index.html +\end{verbatim} + +Option~\verb+--output-direct+ overrules all other output options. + \option{--output-normal} \verb+--output-normal+ As rule commands are executed, relay their output to the \OMake{} output right away. This is enabled diff --git a/src/exec/omake_exec.ml b/src/exec/omake_exec.ml index 18595ca..da2198c 100644 --- a/src/exec/omake_exec.ml +++ b/src/exec/omake_exec.ml @@ -190,17 +190,18 @@ struct in (* Handle a status message *) - let handle_status = print_status (handle_sys_out id) options shell server name in + let handle_status = print_status (handle_sys_out id) options shell server name + and direct_output = Omake_options.(opt_output options OutputDirect) in (* Start the job *) let status = match handle with LocalServer local -> - Omake_exec_local.spawn local shell id handle_out handle_err handle_status target commands + Omake_exec_local.spawn direct_output local shell id handle_out handle_err handle_status target commands | RemoteServer remote -> - Omake_exec_remote.spawn remote shell id handle_out handle_err handle_status target commands + Omake_exec_remote.spawn false remote shell id handle_out handle_err handle_status target commands | NotifyServer notify -> - Notify.spawn notify shell id handle_out handle_err handle_status target commands + Notify.spawn false notify shell id handle_out handle_err handle_status target commands in let () = match status with @@ -224,7 +225,8 @@ struct let handle_eof server_info options fd = match server_info.server_handle with | LocalServer local -> - Omake_exec_local.handle_eof local options fd + let direct_output = Omake_options.(opt_output options OutputDirect) in + Omake_exec_local.handle_eof direct_output local options fd | RemoteServer _ -> () | NotifyServer _ -> diff --git a/src/exec/omake_exec_local.ml b/src/exec/omake_exec_local.ml index 48e2906..7d3c96a 100644 --- a/src/exec/omake_exec_local.ml +++ b/src/exec/omake_exec_local.ml @@ -128,8 +128,11 @@ type fd_state = (* * Start a command. Takes the output channels, and returns a pid. *) - let start_command _server (shell : _ Omake_exec_type.shell) stdout stderr command = - shell.shell_eval stdout stderr command + let start_command direct_output _server (shell : _ Omake_exec_type.shell) stdout stderr command = + if direct_output then + shell.shell_eval Unix.stdout Unix.stderr command + else + shell.shell_eval stdout stderr command let likely_blocking server = @@ -149,7 +152,7 @@ type fd_state = (* * Start a job. *) - let rec spawn_exn server shell id handle_out handle_err handle_status target commands = + let rec spawn_exn direct_output server shell id handle_out handle_err handle_status target commands = let command, commands = match commands with command :: commands -> @@ -163,7 +166,7 @@ type fd_state = in if shell.shell_eval_is_nop command && commands <> [] then (* quickly skip over nop's *) spawn_exn - server shell id handle_out handle_err handle_status target commands + direct_output server shell id handle_out handle_err handle_status target commands else Omake_exec_util.with_pipe (fun out_read out_write -> Omake_exec_util.with_pipe (fun err_read err_write -> @@ -178,7 +181,7 @@ type fd_state = Unix.set_close_on_exec err_read in let now = Unix.gettimeofday() in - let pid = start_command server shell out_write err_write command in + let pid = start_command direct_output server shell out_write err_write command in let job = { job_id = id; job_target = target; @@ -219,8 +222,8 @@ type fd_state = | [] -> () - let spawn server shell id handle_out handle_err handle_status target commands = - try spawn_exn server shell id handle_out handle_err handle_status target commands with + let spawn direct_output server shell id handle_out handle_err handle_status target commands = + try spawn_exn direct_output server shell id handle_out handle_err handle_status target commands with exn -> err_print_status commands handle_status id; handle_exn handle_err shell.shell_print_exn id exn; @@ -232,7 +235,7 @@ type fd_state = (* * Start the next part of the job. *) - let rec spawn_next_part_exn server job = + let rec spawn_next_part_exn direct_output server job = let { job_id = id; job_shell = shell; job_target = _target; @@ -249,7 +252,7 @@ type fd_state = if shell.shell_eval_is_nop command then ( (* quickly skip over nop's *) job.job_commands <- commands; - spawn_next_part_exn server job + spawn_next_part_exn direct_output server job ) else Omake_exec_util.with_pipe (fun out_read out_write -> @@ -259,7 +262,7 @@ type fd_state = Unix.set_close_on_exec out_read; Unix.set_close_on_exec err_read in - let pid = start_command server shell out_write err_write command in + let pid = start_command direct_output server shell out_write err_write command in let table = Omake_exec_util.FdTable.add table out_read job in let table = Omake_exec_util.FdTable.add table err_read job in if !Omake_exec_util.debug_exec then @@ -287,8 +290,8 @@ type fd_state = | JobFinished _ -> raise (Invalid_argument "spawn_next_part") - let spawn_next_part server job = - try spawn_next_part_exn server job with + let spawn_next_part direct_output server job = + try spawn_next_part_exn direct_output server job with exn -> let shell = job.job_shell in err_print_status job.job_commands job.job_handle_status job.job_id; @@ -318,7 +321,7 @@ type fd_state = (* * Wait for the current part to finish. *) - let wait_for_job server options job = + let wait_for_job direct_output server options job = let { job_pid = pid; job_command = command; job_shell = shell ; _} = job in let () = if !Omake_exec_util.debug_exec then @@ -333,7 +336,7 @@ type fd_state = else begin job.job_state <- JobRunning v; - spawn_next_part server job + spawn_next_part direct_output server job end let acknowledge_eof server _options fd = @@ -354,7 +357,7 @@ type fd_state = done, and that we can reuse the job record for the next command *) - let handle_eof server options fd = + let handle_eof direct_output server options fd = let job_opt = try Some (Omake_exec_util.FdTable.find server.server_table fd) with Not_found -> None in @@ -382,7 +385,7 @@ type fd_state = unix_close "handle_eof (stderr)" job.job_stderr; ); if job.job_stdout_done = Fd_closed && job.job_stderr_done = Fd_closed then - wait_for_job server options job + wait_for_job direct_output server options job let unix_read fd buf pos len = try Unix.read fd buf pos len diff --git a/src/exec/omake_exec_notify.ml b/src/exec/omake_exec_notify.ml index 56d8dd7..d713649 100644 --- a/src/exec/omake_exec_notify.ml +++ b/src/exec/omake_exec_notify.ml @@ -149,7 +149,7 @@ struct false - let handle_eof _ _ _ = () + let handle_eof _ _ _ _ = () let acknowledge_eof _ _ _ = () (* diff --git a/src/exec/omake_exec_remote.ml b/src/exec/omake_exec_remote.ml index bb1b816..ab93159 100644 --- a/src/exec/omake_exec_remote.ml +++ b/src/exec/omake_exec_remote.ml @@ -164,6 +164,7 @@ module Server = struct let handle_spawn local shell id target commands = let code = Omake_exec_local.spawn (**) + false local shell id @@ -195,7 +196,7 @@ module Server = struct let closed = Omake_exec_local.handle local options fd in if closed then ( Omake_exec_local.acknowledge_eof local options fd; - Omake_exec_local.handle_eof local options fd + Omake_exec_local.handle_eof false local options fd ) (* @@ -347,7 +348,7 @@ type 'value job_state = (* * Start a new job. *) - let spawn server shell id handle_out handle_err handle_status target commands = + let spawn _direct_output server shell id handle_out handle_err handle_status target commands = if !debug_remote then eprintf "*** remote: spawn: %a@." pp_print_node target; @@ -474,7 +475,7 @@ type 'value job_state = handle_normal server fd - let handle_eof _ _ _ = () + let handle_eof _ _ _ _ = () let acknowledge_eof _ _ _ = () diff --git a/src/exec/omake_exec_type.ml b/src/exec/omake_exec_type.ml index 6483f68..213d301 100644 --- a/src/exec/omake_exec_type.ml +++ b/src/exec/omake_exec_type.ml @@ -87,6 +87,7 @@ sig * Start a command, and return the process ID. *) val spawn : + bool -> (* Bypass all redirections? *) ('exp, 'pid, 'value) t -> (* Current state *) ('exp, 'pid, 'value) shell -> (* The shell that does evaluation *) Omake_exec_id.t -> (* Id for the new process *) @@ -116,7 +117,7 @@ sig (* * Special actions for EOF. (Including closing fd's.) *) - val handle_eof : ('exp, 'pid, 'value) t -> Omake_options.t -> Unix.file_descr -> unit + val handle_eof : bool -> ('exp, 'pid, 'value) t -> Omake_options.t -> Unix.file_descr -> unit (* * Wait for any one of the commands to finish. diff --git a/src/ir/omake_options.ml b/src/ir/omake_options.ml index a8a2967..f37bfdf 100644 --- a/src/ir/omake_options.ml +++ b/src/ir/omake_options.ml @@ -10,6 +10,7 @@ type eval_flag = * Diversion control. *) type output_flag = + | OutputDirect | OutputNormal | OutputPostponeSuccess | OutputPostponeError @@ -338,6 +339,9 @@ let rec opt_output (opts : t) (flag : output_flag) : bool = | None, OutputPostponeSuccess -> (* off by default *) false + | None, OutputDirect -> + (* off by default *) + false let set_output_opt flag opts on = let flags = (flag, on) :: (List.remove_assoc flag opts.output) in @@ -477,6 +481,9 @@ let output_spec = "-w", Lm_arg.SetFold set_print_dir_opt, "Print the directory in \"make format\" as commands are executed"; + "--output-direct", Lm_arg.SetFold (set_output_opt OutputDirect), + "Do not redirect the output on the local machine in any way."; + "--output-normal", Lm_arg.SetFold (set_output_opt OutputNormal), "Relay the output of the rule commands to the OMake output right away. This is the default when no --output-postpone and no --output-only-errors flags are given."; diff --git a/src/ir/omake_options.mli b/src/ir/omake_options.mli index 4f9a8a9..2b6d589 100644 --- a/src/ir/omake_options.mli +++ b/src/ir/omake_options.mli @@ -15,6 +15,7 @@ type eval_flag = * Diversion control. *) type output_flag = + | OutputDirect | OutputNormal | OutputPostponeSuccess | OutputPostponeError