Use diversion when calling external tools with a very long argument list (#9492)
It's not just on Windows that the length of the command passed to Sys.command can exceed system limits: - On Linux there is a per-argument limit of 2^17 bytes (the whole command is a single argument to /bin/sh) - On macOS with default parameters, the limit is between 70000 and 80000 - On BSDs with default parameters, the limit is around 2^18. In parallel, response files (@file) are supported by all the C compilers we've encountered: GCC, Clang, Intel's ICC, and even CompCert. They all seem to follow quoting rules similar to that of the native shell for the contents of the response file. This commit forces the use of a response file when the total size of the arguments to the linker is greater than 2^16. Arguments passed via a response file are quoted using Filename.quote as if they were passed on the command line. Closes: #9482 Closes: #8549master
parent
1e98c52e93
commit
68c6f89409
4
Changes
4
Changes
|
@ -240,6 +240,10 @@ OCaml 4.11
|
|||
Use KEEP_TEST_DIR_ON_SUCCESS=1 to keep all artifacts.
|
||||
(Gabriel Scherer, review by Sébastien Hinderer)
|
||||
|
||||
- #9482, #9492: use diversions (@file) to work around OS limitations
|
||||
on length of Sys.command argument.
|
||||
(Xavier Leroy, report by Jérémie Dimino, review by David Allsopp)
|
||||
|
||||
### Manual and documentation:
|
||||
|
||||
- #9141: beginning of the ocamltest reference manual
|
||||
|
|
|
@ -27,8 +27,17 @@ let command cmdline =
|
|||
|
||||
let run_command cmdline = ignore(command cmdline)
|
||||
|
||||
(* Build @responsefile to work around Windows limitations on
|
||||
command-line length *)
|
||||
(* Build @responsefile to work around OS limitations on
|
||||
command-line length.
|
||||
Under Windows, the max length is 8187 minus the length of the
|
||||
COMSPEC variable (or 7 if it's not set). To be on the safe side,
|
||||
we'll use a response file if we need to pass 4096 or more bytes of
|
||||
arguments.
|
||||
For Unix-like systems, the threshold is 2^16 (64 KiB), which is
|
||||
within the lowest observed limits (2^17 per argument under Linux;
|
||||
between 70000 and 80000 for macOS).
|
||||
*)
|
||||
|
||||
let build_diversion lst =
|
||||
let (responsefile, oc) = Filename.open_temp_file "camlresp" "" in
|
||||
List.iter (fun f -> Printf.fprintf oc "%s\n" f) lst;
|
||||
|
@ -40,7 +49,8 @@ let quote_files lst =
|
|||
let lst = List.filter (fun f -> f <> "") lst in
|
||||
let quoted = List.map Filename.quote lst in
|
||||
let s = String.concat " " quoted in
|
||||
if String.length s >= 4096 && Sys.os_type = "Win32"
|
||||
if String.length s >= 65536
|
||||
|| (String.length s >= 4096 && Sys.os_type = "Win32")
|
||||
then build_diversion quoted
|
||||
else s
|
||||
|
||||
|
|
Loading…
Reference in New Issue