I maintain the distribution of a larger OCaml project (Coq Platform) and one of the OCaml files in there needs a stack size of 64MB for the compiler (ocamlopt.opt.exe) to compile (32 MB is not enough). I know that I can use editbin to change the stack size after the facts on Windows, but there is no open source alternative of editbin I know of. In the OCaml configure file (I am still on 4.14.2) I see:
but I don’t see a way to set flexlink_flags directly in case one doesn’t like the default. Should I just patch the configure file (easy enough in opam)?
What I am unsure of: is the option used for the executables ocamlopt generates or for ocamlopt itself or both?
Unfortunately, there is no way to customize the stack size currently. Patching the ./configure script is one way. You can also use the editbin.exe tool to modify the stack size after the fact (using the /STACK option).
yes, as I wrote I am aware of editbin, but this is about an open source SW distribution and it is difficult to rely on proprietary software - even if it is freely installable.
I will go ahead and patch the configure file via opam.
Sorry, I had missed your mentioning editbin. Incidentally, at LexiFi we had the same need to avoid depending on the MSVC toolchain so we just reimplemented the needed functionality in OCaml
(* Modify the stack size of the resulting PE executable.
See https://learn.microsoft.com/en-us/windows/win32/debug/pe-format for a
description of the PE format. *)
let perform ~__FUNCTION__ f fd ofs len buf =
if Bytes.length buf < len then invalid_arg __FUNCTION__;
let _ = Unix.lseek fd ofs SEEK_SET in
let rec loop ofs len =
if len <= 0 then ()
else begin
let n = f fd buf ofs len in
if n = 0 then raise End_of_file;
loop (ofs + n) (len - n)
end
in
loop 0 len
let really_read = perform ~__FUNCTION__ Unix.read
let really_write = perform ~__FUNCTION__ Unix.write
let read_bytes fd ofs len =
let buf = Bytes.create len in
really_read fd ofs len buf;
Bytes.unsafe_to_string buf
let read_int f len fd ofs =
f (read_bytes fd ofs len) 0
let read_int32 = read_int String.get_int32_le 4
let read_int16 = read_int String.get_int16_le 2
let write_int f len =
let buf = Bytes.create len in
fun fd ofs n ->
f buf 0 n;
really_write fd ofs len buf
let write_int64 = write_int Bytes.set_int64_le 8
let set_stack_size out n =
assert (Sys.word_size = 64);
let fd = Unix.openfile out [O_RDWR; O_SHARE_DELETE] 0o755 in
let base = Option.get (Int32.unsigned_to_int (read_int32 fd 0x3c)) in
let sign = read_bytes fd base 4 in
if sign <> "PE\000\000" then Printf.ksprintf failwith "Invalid PE Signature: %S" sign;
let base = base + 24 in
let sign = read_int16 fd base in
if sign <> 0x20b then Printf.ksprintf failwith "Invalid PE Optional Header Signature: 0x%x" sign;
write_int64 fd (base + 72) n
great, many thanks! This solution has the advantage that I can supply a script to patch ocamlc and coqc after the fact as needed by the user. Usually one does not know in advance the stack size one will need and quite a few researchers would appreciate if they could just try if their code would work with just a larger stack size.
IMHO it would be worthwhile to supply this tool as opam package on Windows.