From e0a90f2cae6a3f220e5bc3b280d98f35aba5ad32 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 26 Feb 2017 22:54:38 +0000 Subject: [PATCH] Separate the treatment of build and host toolchains. A plugin is always built for the same platform ocamlbuild is. It is therefore always a mistake to pass the -toolchain option to ocamlfind when building a plugin. More generally, the compiler that is used for building the plugin and the user code should be possible to set separately. This necessarily results in four new command-line options: * -plugin-ocaml{c,opt}, which are like -ocaml{c,opt} but only for building the plugin; * -plugin-{no,use}-ocamlfind, which are like -{no,use}-ocamlfind, but only for building the plugin. To preserve compatibility, the old -{use,no}-ocamlfind options imply the new -plugin-{use,no}-ocamlfind. It is still possible to have any combination of using ocamlfind for build or host code by ordering the -plugin-{use,no}-ocamlfind options after -{use,no}-ocamlfind ones. Note that the -cflag, -lflag, etc., options were never used when building the plugin and are therefore not touched by this commit. --- src/options.ml | 74 ++++++++++++++++++++++++++++++++-------------- src/plugin.ml | 11 ++++--- src/signatures.mli | 3 ++ 3 files changed, 59 insertions(+), 29 deletions(-) diff --git a/src/options.ml b/src/options.ml index febbc9b3..9077e6e8 100644 --- a/src/options.ml +++ b/src/options.ml @@ -39,6 +39,7 @@ let nostdlib = ref false let use_menhir = ref false let catch_errors = ref true let use_ocamlfind = ref false +let plugin_use_ocamlfind = ref false let toolchain = ref "" (* Currently only ocamlfind and menhir is defined as no-core tool, @@ -85,7 +86,9 @@ let () = ["ocamlc"; "ocamlopt"; "ocamldep"; "ocamldoc"; "ocamlyacc"; "menhir"; "ocamllex"; "ocamlmklib"; "ocamlmktop"; "ocamlfind"] let ocamlc = ref (V"OCAMLC") +let plugin_ocamlc = ref (V"OCAMLC") let ocamlopt = ref (V"OCAMLOPT") +let plugin_ocamlopt = ref (V"OCAMLOPT") let ocamldep = ref (V"OCAMLDEP") let ocamldoc = ref (V"OCAMLDOC") let ocamlyacc = ref N @@ -99,6 +102,7 @@ let ocamlfind arg = S[!ocamlfind_cmd; arg] else S[!ocamlfind_cmd; A"-toolchain"; A!toolchain; arg] +let plugin_ocamlfind arg = S[!ocamlfind_cmd; arg] let program_to_execute = ref false let must_clean = ref false let show_documentation = ref false @@ -142,7 +146,9 @@ let dummy = "*invalid-dummy-string*";; (* Dummy string for delimiting the latest * multiple/installed plugins *) let use_jocaml () = ocamlc := A "jocamlc"; + plugin_ocamlc := A "jocamlc"; ocamlopt := A "jocamlopt"; + plugin_ocamlopt := A "jocamlopt"; ocamldep := A "jocamldep"; ocamlyacc := A "jocamlyacc"; ocamllex := A "jocamllex"; @@ -234,11 +240,16 @@ let spec = ref ( "-classic-display", Set Log.classic_display, " Display executed commands the old-fashioned way"; "-use-menhir", Set use_menhir, " Use menhir instead of ocamlyacc"; "-use-jocaml", Unit use_jocaml, " Use jocaml compilers instead of ocaml ones"; - "-use-ocamlfind", Set use_ocamlfind, " Use the 'ocamlfind' wrapper instead of \ + "-use-ocamlfind", Unit (fun () -> use_ocamlfind := true; plugin_use_ocamlfind := true), " Use the 'ocamlfind' wrapper instead of \ using Findlib directly to determine command-line arguments. \ - Use -no-ocamlfind to disable."; - "-no-ocamlfind", Clear use_ocamlfind, " Don't use ocamlfind."; - "-toolchain", Set_string toolchain, " Set the Findlib toolchain to use."; + Use -no-ocamlfind to disable. Implies -plugin-use-ocamlfind."; + "-no-ocamlfind", Unit (fun () -> use_ocamlfind := false; plugin_use_ocamlfind := false), " Don't use ocamlfind. Implies -plugin-no-ocamlfind."; + "-plugin-use-ocamlfind", Set plugin_use_ocamlfind, " Use the 'ocamlfind' wrapper \ + for building myocamlbuild.ml"; + "-plugin-no-ocamlfind", Clear plugin_use_ocamlfind, " Don't use ocamlfind \ + for building myocamlbuild.ml"; + "-toolchain", Set_string toolchain, " Set the Findlib toolchain to use. \ + The default toolchain is always used for building myocamlbuild.ml."; "-j", Set_int Command.jobs, " Allow N jobs at once (0 for unlimited)"; @@ -248,7 +259,11 @@ let spec = ref ( "-where", Unit (fun () -> print_endline !Ocamlbuild_where.libdir; raise Exit_OK), " Display the install library directory"; "-which", String (fun cmd -> print_endline (find_tool cmd); raise Exit_OK), " Display path to the tool command"; "-ocamlc", set_cmd ocamlc, " Set the OCaml bytecode compiler"; + "-plugin-ocamlc", set_cmd plugin_ocamlc, " Set the OCaml bytecode compiler \ + used when building myocamlbuild.ml (only)"; "-ocamlopt", set_cmd ocamlopt, " Set the OCaml native compiler"; + "-plugin-ocamlopt", set_cmd plugin_ocamlopt, " Set the OCaml native compiler \ + used when building myocamlbuild.ml (only)"; "-ocamldep", set_cmd ocamldep, " Set the OCaml dependency tool"; "-ocamldoc", set_cmd ocamldoc, " Set the OCaml documentation generator"; "-ocamlyacc", set_cmd ocamlyacc, " Set the ocamlyacc tool"; @@ -305,34 +320,47 @@ let init () = Log.init log in + let with_ocamlfind (ocamlfind, command_name, command_ref) = + command_ref := match !command_ref with + | Sh user_command -> + (* this command has been set by the user + using an -ocamlc, -ocamlopt, etc. flag; + + not all such combinations make sense (eg. "ocamlfind + /my/special/path/to/ocamlc" will make ocamlfind choke), + but the user will see the error and hopefully fix the + flags. *) + ocamlfind & (Sh user_command); + | _ -> ocamlfind & A command_name + in + if !use_ocamlfind then begin begin try ignore(Command.search_in_path "ocamlfind") with Not_found -> failwith "ocamlfind not found on path, but -no-ocamlfind not used" end; - let with_ocamlfind (command_name, command_ref) = - command_ref := match !command_ref with - | Sh user_command -> - (* this command has been set by the user - using an -ocamlc, -ocamlopt, etc. flag; - - not all such combinations make sense (eg. "ocamlfind - /my/special/path/to/ocamlc" will make ocamlfind choke), - but the user will see the error and hopefully fix the - flags. *) - ocamlfind & (Sh user_command); - | _ -> ocamlfind & A command_name - in (* Note that plugins can still modify these variables After_options. This design decision can easily be changed. *) List.iter with_ocamlfind [ - "ocamlc", ocamlc; - "ocamlopt", ocamlopt; - "ocamldep", ocamldep; - "ocamldoc", ocamldoc; - "ocamlmklib", ocamlmklib; - "ocamlmktop", ocamlmktop; + ocamlfind, "ocamlc", ocamlc; + ocamlfind, "ocamlopt", ocamlopt; + ocamlfind, "ocamldep", ocamldep; + ocamlfind, "ocamldoc", ocamldoc; + ocamlfind, "ocamlmklib", ocamlmklib; + ocamlfind, "ocamlmktop", ocamlmktop; + ] + end; + + if !plugin_use_ocamlfind then begin + begin try ignore(Command.search_in_path "ocamlfind") + with Not_found -> + failwith "ocamlfind not found on path, but -no-plugin-ocamlfind not used" + end; + + List.iter with_ocamlfind [ + plugin_ocamlfind, "ocamlc", plugin_ocamlc; + plugin_ocamlfind, "ocamlopt", plugin_ocamlopt; ] end; diff --git a/src/plugin.ml b/src/plugin.ml index 062467e9..451f7ece 100644 --- a/src/plugin.ml +++ b/src/plugin.ml @@ -86,18 +86,17 @@ module Make(U:sig end) = let cma, cmo, compiler, byte_or_native = if !Options.native_plugin then - "cmxa", "cmx", !Options.ocamlopt, "native" + "cmxa", "cmx", !Options.plugin_ocamlopt, "native" else - "cma", "cmo", !Options.ocamlc, "byte" + "cma", "cmo", !Options.plugin_ocamlc, "byte" in - let (unix_spec, ocamlbuild_lib_spec, ocamlbuild_module_spec) = let use_light_mode = not !Options.native_plugin && !*My_unix.is_degraded in let use_ocamlfind_pkgs = - !Options.use_ocamlfind && !Options.plugin_tags <> [] in + !Options.plugin_use_ocamlfind && !Options.plugin_tags <> [] in (* The plugin has the following dependencies that must be included during compilation: @@ -127,7 +126,7 @@ module Make(U:sig end) = to support modular construction of ocamlbuild plugins). Indeed, if we hard-code linking to unix.cmxa in all cases, and the user - enables -use-ocamlfind and + enables -plugin-use-ocamlfind and passes -plugin-tag "package(unix)" (or package(foo) for any foo which depends on unix), the command-line finally executed will be @@ -146,7 +145,7 @@ module Make(U:sig end) = We switch to this behavior when two conditions, embodied in the boolean variable [use_ocamlfind_pkgs], are met: - (a) use-ocamlfind is enabled + (a) plugin-use-ocamlfind is enabled (b) the user is passing some plugin tags Condition (a) is overly conservative as the double-linking diff --git a/src/signatures.mli b/src/signatures.mli index f2f0c8d5..a6d0a2f1 100644 --- a/src/signatures.mli +++ b/src/signatures.mli @@ -382,7 +382,9 @@ module type OPTIONS = sig val exclude_dirs : string list ref val nothing_should_be_rebuilt : bool ref val ocamlc : command_spec ref + val plugin_ocamlc : command_spec ref val ocamlopt : command_spec ref + val plugin_ocamlopt : command_spec ref val ocamldep : command_spec ref val ocamldoc : command_spec ref val ocamlyacc : command_spec ref @@ -406,6 +408,7 @@ module type OPTIONS = sig val show_documentation : bool ref val recursive : bool ref val use_ocamlfind : bool ref + val plugin_use_ocamlfind : bool ref val targets : string list ref val ocaml_libs : string list ref