From ebe44c6b1fbce0ff711fb08d3f48584b13449c9d Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 26 Feb 2017 20:32:49 +0000 Subject: [PATCH] Let autolink do its job when linking .cmxs files. Before the recent .cmxs refactor, i.e. 89888f2c4...f865497a8, .cmxs files were built from .cmx and .o files. After commit f865497a8, .cmxs files are built from .cmxa and .a files, which is wrong, because .cmxa files already contain the autolink instructions necessary to link the .a file; and on top of that, no -I flag was provided when linking the .cmxs file, which resulted in the linker being unable to follow the autolink instructions. This caused failures in the wild when ocamlbuild 0.10.0 got released: https://github.com/ocaml/opam-repository/pull/8157. After this commit, .a files are no longer explicitly passed when building a .cmxs file. Additionally, for every linked file, a -I flag is passed, with the directory containing the file being linked. --- src/ocaml_compiler.ml | 13 ++++++++----- src/ocaml_specific.ml | 6 +++--- testsuite/internal.ml | 26 ++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/ocaml_compiler.ml b/src/ocaml_compiler.ml index e6d5becf..b05fe920 100644 --- a/src/ocaml_compiler.ml +++ b/src/ocaml_compiler.ml @@ -30,6 +30,11 @@ let forpack_flags arg tags = Ocaml_arch.forpack_flags_of_pathname arg else N +let include_flags_for_deps deps = + let dirnames = List.union [] (List.map Pathname.dirname deps) in + let include_flags = List.fold_right ocaml_add_include_flag dirnames [] in + S include_flags + let ocamlc_c tags arg out = let tags = tags++"ocaml"++"byte" in Cmd (S [!Options.ocamlc; A"-c"; T(tags++"compile"); @@ -37,7 +42,7 @@ let ocamlc_c tags arg out = let ocamlc_link flag tags deps out = Cmd (S [!Options.ocamlc; flag; T tags; - atomize_paths deps; A"-o"; Px out]) + include_flags_for_deps deps; atomize_paths deps; A"-o"; Px out]) let ocamlc_link_lib = ocamlc_link (A"-a") let ocamlc_link_prog = ocamlc_link N @@ -70,19 +75,17 @@ let ocamlopt_c tags arg out = let ocamlopt_link flag tags deps out = Cmd (S [!Options.ocamlopt; flag; forpack_flags out tags; T tags; - atomize_paths deps; A"-o"; Px out]) + include_flags_for_deps deps; atomize_paths deps; A"-o"; Px out]) let ocamlopt_link_lib = ocamlopt_link (A"-a") let ocamlopt_link_shared_lib = ocamlopt_link (A"-shared") let ocamlopt_link_prog = ocamlopt_link N let ocamlopt_p tags deps out = - let dirnames = List.union [] (List.map Pathname.dirname deps) in - let include_flags = List.fold_right ocaml_add_include_flag dirnames [] in let mli = Pathname.update_extensions "mli" out in let cmd = S [!Options.ocamlopt; A"-pack"; forpack_flags out tags; T tags; - S include_flags; atomize_paths deps; + include_flags_for_deps deps; atomize_paths deps; A"-o"; Px out] in if (*FIXME true ||*) Pathname.exists mli then Cmd cmd else diff --git a/src/ocaml_specific.ml b/src/ocaml_specific.ml index 35f0f3d9..79b37a40 100644 --- a/src/ocaml_specific.ml +++ b/src/ocaml_specific.ml @@ -393,12 +393,12 @@ rule "ocaml: cmx & o -> cmxa & a" rule "ocaml: p.cmxa & p.a -> p.cmxs & p.so" ~prods:["%.p.cmxs"; x_p_dll] - ~deps:["%.p.cmxa"; x_p_a] + ~deps:["%.p.cmxa"] (Ocaml_compiler.native_shared_library_link ~tags:["profile";"linkall"] "%.p.cmxa" "%.p.cmxs");; -rule "ocaml: cmxa & a -> cmxs & so" +rule "ocaml: cmxa -> cmxs & so" ~prods:["%.cmxs"; x_dll] - ~deps:["%.cmxa"; x_a] + ~deps:["%.cmxa"] ~doc:"This rule allows to build a .cmxs from a .cmxa, to avoid having \ to duplicate a .mllib file into a .mldylib." (Ocaml_compiler.native_shared_library_link ~tags:["linkall"] "%.cmxa" "%.cmxs");; diff --git a/testsuite/internal.ml b/testsuite/internal.ml index 8a13b55d..5198579b 100644 --- a/testsuite/internal.ml +++ b/testsuite/internal.ml @@ -167,6 +167,32 @@ let () = test "OutputShared" T.f "_tags" ~content:"<*.so>: runtime_variant(_pic)"] ~targets:("hello.byte.so",["hello.native.so"]) ();; +let () = test "CmxsStubLink" + ~options:[`no_ocamlfind] + ~description:".cmxs link rules pass correct -I flags" + ~tree:[T.d "src" [ + T.f "foo_stubs.c" ~content:""; + T.f "libfoo_stubs.clib" ~content:"foo_stubs.o"; + T.f "foo.ml" ~content:""; + ]; + T.f "_tags" ~content:" + : record_foo_stubs + : link_foo_stubs"; + T.f "myocamlbuild.ml" ~content:" +open Ocamlbuild_plugin +let () = + dispatch begin function + | After_rules -> + dep [\"record_foo_stubs\"] [\"src/libfoo_stubs.a\"]; + flag_and_dep + [\"link\"; \"ocaml\"; \"link_foo_stubs\"] (P \"src/libfoo_stubs.a\"); + flag [\"library\"; \"ocaml\"; \"record_foo_stubs\"] + (S ([A \"-cclib\"; A \"-lfoo_stubs\"])); + | _ -> () + end +"] + ~targets:("src/foo.cmxs",[]) ();; + let () = test "StrictSequenceFlag" ~options:[`no_ocamlfind; `quiet] ~description:"strict_sequence tag"