Skip to content

Commit

Permalink
Native Windows support
Browse files Browse the repository at this point in the history
1. AST files need to be written in binary mode
   on Windows, or else:

    File "metapp/dune", line 3, characters 14-30:
    3 |   (preprocess (pps metapp.ppx))
                      ^^^^^^^^^^^^^^^^
    (cd _build/default && .ppx/e7c203cacf1cd3bb02e6242329effa31/ppx.exe --cookie "library-name=\"metapp\"" -o metapp/metapp.pp.mli --intf metapp/metapp.mli -corrected-suffix .ppx-corrected -diff-cmd - -dump-ast)
    Fatal error: exception Failure("output_value: not a binary channel")
    Raised by primitive operation at Stdlib.output_value in file "stdlib.ml", line 386, characters 26-54
    Called from Dyncompile.write_ast in file "dyncompile/dyncompile.ml", line 82, characters 6-47
    Called from Stdlib__Fun.protect in file "fun.ml", line 33, characters 8-15
    Re-raised at Stdlib__Fun.protect in file "fun.ml", line 38, characters 6-52
    Called from Dyncompile.compile_and_load.(fun) in file "dyncompile/dyncompile.ml", line 90, characters 4-126
    Called from Stdlib__Fun.protect in file "fun.ml", line 33, characters 8-15
    Re-raised at Stdlib__Fun.protect in file "fun.ml", line 38, characters 6-52
    Called from Metapp_ppx.transform in file "ppx/metapp_ppx.ml", line 418, characters 4-101
    Called from Ppxlib__Driver.Transform.register.(fun) in file "src/driver.ml", line 190, characters 61-72
    Called from Ppxlib__Driver.apply_transforms.(fun) in file "src/driver.ml", line 574, characters 20-28
    Called from Stdlib__List.fold_left in file "list.ml", line 121, characters 24-34
    Called from Ppxlib__Driver.apply_transforms in file "src/driver.ml", line 551, characters 6-1023
    Called from Ppxlib__Driver.map_signature_gen in file "src/driver.ml", line 785, characters 4-336
    Called from Ppxlib__Driver.process_ast in file "src/driver.ml", line 1066, characters 10-127
    Called from Ppxlib__Driver.process_file in file "src/driver.ml", line 1120, characters 15-111
    Called from Ppxlib__Driver.standalone in file "src/driver.ml", line 1541, characters 9-27
    Re-raised at Location.report_exception.loop in file "parsing/location.ml", line 938, characters 14-25
    Called from Ppxlib__Driver.standalone in file "src/driver.ml", line 1544, characters 4-59
    Called from Dune__exe___ppx in file ".ppx/e7c203cacf1cd3bb02e6242329effa31/_ppx.ml-gen", line 1, characters 9-36
    File "metapp/dune", line 3, characters 14-30:

2. Dynlink.loadfile opens a temp file, and on Windows you can't
   delete an open file. Since the file never closes
   until the process dies, on Windows we let
   the temporary file stay on disk. The owner of
   the temporary directory (Dune) will erase
   the directory and the seemingly leaked temporary
   file

3. On native Windows the compiler environment does not need to
   be fixed. The MSVC compiler and linker should be on the PATH
   with INCLUDE and LIB environment variables as well when
   run from the Visual Studio Command Prompt or using a native
   Windows distribution like DkML.
  • Loading branch information
jonahbeckford committed Jul 3, 2023
1 parent f8b200c commit cb7ec40
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*~
/_build/
/_opam/
.merlin
/metapp.install
16 changes: 13 additions & 3 deletions dyncompile/dyncompile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ let rec try_commands ~verbose list =
if verbose then
prerr_endline command_line;
let env = Unix.environment () in
fix_compiler_env env;
if not Sys.win32 then fix_compiler_env env;
let channels = Unix.open_process_full command_line env in
let (compiler_stdout, _, compiler_stderr) = channels in
let compiler_stdout = In_channel.input_all compiler_stdout in
Expand Down Expand Up @@ -121,7 +121,8 @@ let write_ast (plainsource : bool) (channel : out_channel)

let compile_and_load (options : Options.t) (structure : Parsetree.structure)
: unit =
let (source_filename, channel) = Filename.open_temp_file "metapp" ".ml" in
let (source_filename, channel) =
Filename.open_temp_file ~mode:[Open_binary] "metapp" ".ml" in
Fun.protect (fun () ->
Fun.protect (fun () ->
write_ast options.plainsource channel structure)
Expand All @@ -130,6 +131,15 @@ let compile_and_load (options : Options.t) (structure : Parsetree.structure)
Filename.remove_extension source_filename ^
compiler.archive_suffix in
compile options source_filename object_filename;
Unix.chmod object_filename 0o640;
Fun.protect (fun () -> Dynlink.loadfile object_filename)
~finally:(fun () -> Sys.remove object_filename))
~finally:(fun () ->
(* Windows is an OS that does not let deletes occur when the file
is still open. Dynlink.loadfile opens the file and does not close
it even in [at_exit]. It is probably an OCaml bug that there is
not way to close after Dynlink.loadfile, so we mitigate by just
keeping the file around. [dune build] will remove the temporary
directory (ex. build_3d445b_dune) regardless, so no resource leak
when using Dune. *)
if not Sys.win32 then Sys.remove object_filename))
~finally:(fun () -> (*Sys.remove source_filename*)())

0 comments on commit cb7ec40

Please sign in to comment.