2016-12-02 13:54:32 +00:00
|
|
|
open Import
|
2018-02-06 14:39:03 +00:00
|
|
|
open Fiber.O
|
2016-12-02 13:54:32 +00:00
|
|
|
|
|
|
|
module Kind = struct
|
2017-02-26 21:28:30 +00:00
|
|
|
module Opam = struct
|
|
|
|
type t =
|
|
|
|
{ root : string
|
|
|
|
; switch : string
|
|
|
|
}
|
|
|
|
end
|
|
|
|
type t = Default | Opam of Opam.t
|
2017-03-10 11:22:01 +00:00
|
|
|
|
|
|
|
let sexp_of_t : t -> Sexp.t = function
|
2018-02-24 23:33:26 +00:00
|
|
|
| Default -> Sexp.unsafe_atom_of_string "default"
|
2017-03-10 11:22:01 +00:00
|
|
|
| Opam o ->
|
2018-02-24 23:33:26 +00:00
|
|
|
Sexp.To_sexp.(record [ "root" , string o.root
|
|
|
|
; "switch", string o.switch
|
2017-03-10 11:22:01 +00:00
|
|
|
])
|
2016-12-02 13:54:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
type t =
|
2017-02-25 00:28:10 +00:00
|
|
|
{ name : string
|
|
|
|
; kind : Kind.t
|
2018-05-04 15:49:25 +00:00
|
|
|
; profile : string
|
2017-02-26 20:53:32 +00:00
|
|
|
; merlin : bool
|
2016-12-02 13:54:32 +00:00
|
|
|
; for_host : t option
|
2017-12-21 11:54:00 +00:00
|
|
|
; implicit : bool
|
2016-12-02 13:54:32 +00:00
|
|
|
; build_dir : Path.t
|
|
|
|
; path : Path.t list
|
2017-02-28 06:31:02 +00:00
|
|
|
; toplevel_path : Path.t option
|
2016-12-02 13:54:32 +00:00
|
|
|
; ocaml_bin : Path.t
|
|
|
|
; ocaml : Path.t
|
|
|
|
; ocamlc : Path.t
|
|
|
|
; ocamlopt : Path.t option
|
|
|
|
; ocamldep : Path.t
|
|
|
|
; ocamlmklib : Path.t
|
2018-03-10 14:15:02 +00:00
|
|
|
; env : Env.t
|
2017-02-28 06:01:27 +00:00
|
|
|
; findlib : Findlib.t
|
2017-12-21 11:54:00 +00:00
|
|
|
; findlib_toolchain : string option
|
2016-12-02 13:54:32 +00:00
|
|
|
; arch_sixtyfour : bool
|
2017-02-28 06:01:27 +00:00
|
|
|
; opam_var_cache : (string, string) Hashtbl.t
|
2017-03-07 11:36:59 +00:00
|
|
|
; natdynlink_supported : bool
|
2018-03-06 17:52:28 +00:00
|
|
|
; ocaml_config : Ocaml_config.t
|
2018-02-08 10:12:46 +00:00
|
|
|
; version_string : string
|
|
|
|
; version : int * int * int
|
2016-12-02 13:54:32 +00:00
|
|
|
; stdlib_dir : Path.t
|
|
|
|
; ccomp_type : string
|
2017-03-31 16:31:55 +00:00
|
|
|
; c_compiler : string
|
2018-03-06 12:18:21 +00:00
|
|
|
; ocamlc_cflags : string list
|
|
|
|
; ocamlopt_cflags : string list
|
|
|
|
; bytecomp_c_libraries : string list
|
|
|
|
; native_c_libraries : string list
|
2018-03-06 17:48:06 +00:00
|
|
|
; cc_profile : string list
|
2016-12-02 13:54:32 +00:00
|
|
|
; architecture : string
|
|
|
|
; system : string
|
|
|
|
; ext_obj : string
|
|
|
|
; ext_asm : string
|
|
|
|
; ext_lib : string
|
|
|
|
; ext_dll : string
|
2018-03-06 12:18:21 +00:00
|
|
|
; ext_exe : string
|
2016-12-02 13:54:32 +00:00
|
|
|
; os_type : string
|
|
|
|
; default_executable_name : string
|
|
|
|
; host : string
|
|
|
|
; target : string
|
|
|
|
; flambda : bool
|
|
|
|
; exec_magic_number : string
|
|
|
|
; cmi_magic_number : string
|
|
|
|
; cmo_magic_number : string
|
|
|
|
; cma_magic_number : string
|
|
|
|
; cmx_magic_number : string
|
|
|
|
; cmxa_magic_number : string
|
|
|
|
; ast_impl_magic_number : string
|
|
|
|
; ast_intf_magic_number : string
|
|
|
|
; cmxs_magic_number : string
|
|
|
|
; cmt_magic_number : string
|
2017-03-01 11:04:32 +00:00
|
|
|
; which_cache : (string, Path.t option) Hashtbl.t
|
2016-12-02 13:54:32 +00:00
|
|
|
}
|
|
|
|
|
2017-03-10 11:22:01 +00:00
|
|
|
let sexp_of_t t =
|
|
|
|
let open Sexp.To_sexp in
|
|
|
|
let path = Path.sexp_of_t in
|
|
|
|
record
|
2018-02-24 23:33:26 +00:00
|
|
|
[ "name", string t.name
|
2017-03-10 11:22:01 +00:00
|
|
|
; "kind", Kind.sexp_of_t t.kind
|
2018-05-04 15:49:25 +00:00
|
|
|
; "profile", string t.profile
|
2017-03-10 11:22:01 +00:00
|
|
|
; "merlin", bool t.merlin
|
2018-02-24 23:33:26 +00:00
|
|
|
; "for_host", option string (Option.map t.for_host ~f:(fun t -> t.name))
|
2017-03-10 11:22:01 +00:00
|
|
|
; "build_dir", path t.build_dir
|
|
|
|
; "toplevel_path", option path t.toplevel_path
|
|
|
|
; "ocaml_bin", path t.ocaml_bin
|
|
|
|
; "ocaml", path t.ocaml
|
|
|
|
; "ocamlc", path t.ocamlc
|
|
|
|
; "ocamlopt", option path t.ocamlopt
|
|
|
|
; "ocamldep", path t.ocamldep
|
|
|
|
; "ocamlmklib", path t.ocamlmklib
|
2018-03-29 15:58:41 +00:00
|
|
|
; "env", Env.sexp_of_t (Env.diff t.env Env.initial)
|
2017-03-10 11:22:01 +00:00
|
|
|
; "findlib_path", list path (Findlib.path t.findlib)
|
|
|
|
; "arch_sixtyfour", bool t.arch_sixtyfour
|
|
|
|
; "natdynlink_supported", bool t.natdynlink_supported
|
2018-02-24 23:33:26 +00:00
|
|
|
; "opam_vars", string_hashtbl string t.opam_var_cache
|
2018-03-06 17:52:28 +00:00
|
|
|
; "ocaml_config", Ocaml_config.sexp_of_t t.ocaml_config
|
2018-02-24 23:33:26 +00:00
|
|
|
; "which", string_hashtbl (option path) t.which_cache
|
2017-03-10 11:22:01 +00:00
|
|
|
]
|
|
|
|
|
2017-02-25 14:15:52 +00:00
|
|
|
let compare a b = compare a.name b.name
|
|
|
|
|
2017-02-24 15:41:52 +00:00
|
|
|
let opam_config_var ~env ~cache var =
|
|
|
|
match Hashtbl.find cache var with
|
2018-02-06 14:39:03 +00:00
|
|
|
| Some _ as x -> Fiber.return x
|
2017-02-24 15:41:52 +00:00
|
|
|
| None ->
|
|
|
|
match Bin.opam with
|
2018-02-06 14:39:03 +00:00
|
|
|
| None -> Fiber.return None
|
2017-02-24 15:41:52 +00:00
|
|
|
| Some fn ->
|
2018-04-25 09:30:18 +00:00
|
|
|
Process.run_capture (Accept All) fn ~env
|
2018-03-06 14:56:24 +00:00
|
|
|
["config"; "var"; var]
|
2017-07-05 13:40:00 +00:00
|
|
|
>>| function
|
|
|
|
| Ok s ->
|
|
|
|
let s = String.trim s in
|
2018-02-25 16:35:25 +00:00
|
|
|
Hashtbl.add cache var s;
|
2017-07-05 13:40:00 +00:00
|
|
|
Some s
|
|
|
|
| Error _ -> None
|
2017-02-24 15:41:52 +00:00
|
|
|
|
2017-03-01 11:04:32 +00:00
|
|
|
let which ~cache ~path x =
|
|
|
|
Hashtbl.find_or_add cache x ~f:(Bin.which ~path)
|
|
|
|
|
2018-03-20 16:43:51 +00:00
|
|
|
let ocamlpath_sep =
|
|
|
|
if Sys.cygwin then
|
|
|
|
(* because that's what ocamlfind expects *)
|
|
|
|
';'
|
|
|
|
else
|
|
|
|
Bin.path_sep
|
|
|
|
|
2018-05-04 15:49:25 +00:00
|
|
|
let create ~(kind : Kind.t) ~path ~env ~name ~merlin ~targets ~profile () =
|
2017-02-24 15:41:52 +00:00
|
|
|
let opam_var_cache = Hashtbl.create 128 in
|
|
|
|
(match kind with
|
|
|
|
| Opam { root; _ } ->
|
2018-02-25 16:35:25 +00:00
|
|
|
Hashtbl.add opam_var_cache "root" root
|
2017-02-24 15:41:52 +00:00
|
|
|
| Default -> ());
|
2016-12-02 13:54:32 +00:00
|
|
|
let prog_not_found_in_path prog =
|
2017-03-31 16:31:55 +00:00
|
|
|
Utils.program_not_found prog ~context:name
|
2016-12-02 13:54:32 +00:00
|
|
|
in
|
2017-03-01 11:04:32 +00:00
|
|
|
let which_cache = Hashtbl.create 128 in
|
|
|
|
let which x = which ~cache:which_cache ~path x in
|
2017-12-21 11:54:00 +00:00
|
|
|
let findlib_config_path = lazy (
|
|
|
|
match which "ocamlfind" with
|
|
|
|
| None -> prog_not_found_in_path "ocamlfind"
|
|
|
|
| Some fn ->
|
2018-03-29 15:58:41 +00:00
|
|
|
(* When OCAMLFIND_CONF is set, "ocamlfind printconf" does print
|
|
|
|
the contents of the variable, but "ocamlfind printconf conf"
|
|
|
|
still prints the configuration file set at the configuration
|
|
|
|
time of ocamlfind, sigh... *)
|
2018-05-03 14:28:32 +00:00
|
|
|
(match Env.get env "OCAMLFIND_CONF" with
|
|
|
|
| Some s -> Fiber.return s
|
|
|
|
| None -> Process.run_capture_line ~env Strict fn ["printconf"; "conf"])
|
2018-06-02 11:14:44 +00:00
|
|
|
>>| Path.of_filename_relative_to_initial_cwd)
|
2016-12-02 13:54:32 +00:00
|
|
|
in
|
2017-12-21 11:54:00 +00:00
|
|
|
|
|
|
|
let create_one ~name ~implicit ?findlib_toolchain ?host ~merlin () =
|
|
|
|
(match findlib_toolchain with
|
2018-02-06 14:39:03 +00:00
|
|
|
| None -> Fiber.return None
|
2017-12-21 11:54:00 +00:00
|
|
|
| Some toolchain ->
|
|
|
|
Lazy.force findlib_config_path >>| fun path ->
|
|
|
|
Some (Findlib.Config.load path ~toolchain ~context:name))
|
|
|
|
>>= fun findlib_config ->
|
|
|
|
|
|
|
|
let get_tool_using_findlib_config prog =
|
2018-02-17 05:52:13 +00:00
|
|
|
Option.bind findlib_config ~f:(fun conf ->
|
2017-12-21 11:54:00 +00:00
|
|
|
match Findlib.Config.get conf prog with
|
2018-02-20 11:46:10 +00:00
|
|
|
| None -> None
|
|
|
|
| Some s ->
|
2017-12-21 11:54:00 +00:00
|
|
|
match Filename.analyze_program_name s with
|
|
|
|
| In_path | Relative_to_current_dir -> which s
|
2018-06-02 11:14:44 +00:00
|
|
|
| Absolute -> Some (Path.of_filename_relative_to_initial_cwd s))
|
2017-12-21 11:54:00 +00:00
|
|
|
in
|
|
|
|
|
|
|
|
let ocamlc =
|
|
|
|
match get_tool_using_findlib_config "ocamlc" with
|
|
|
|
| Some x -> x
|
2017-07-25 16:07:24 +00:00
|
|
|
| None ->
|
2017-12-21 11:54:00 +00:00
|
|
|
match which "ocamlc" with
|
|
|
|
| Some x -> x
|
|
|
|
| None -> prog_not_found_in_path "ocamlc"
|
|
|
|
in
|
2018-05-08 16:56:58 +00:00
|
|
|
let dir = Path.parent_exn ocamlc in
|
2017-12-21 11:54:00 +00:00
|
|
|
let ocaml_tool_not_found prog =
|
|
|
|
die "ocamlc found in %s, but %s/%s doesn't exist (context: %s)"
|
|
|
|
(Path.to_string dir) (Path.to_string dir) prog name
|
|
|
|
in
|
|
|
|
let get_ocaml_tool prog =
|
|
|
|
match get_tool_using_findlib_config prog with
|
|
|
|
| None -> Bin.best_prog dir prog
|
|
|
|
| Some _ as x -> x
|
|
|
|
in
|
|
|
|
let get_ocaml_tool_exn prog =
|
|
|
|
match get_ocaml_tool prog with
|
|
|
|
| None -> ocaml_tool_not_found prog
|
|
|
|
| Some fn -> fn
|
|
|
|
in
|
|
|
|
|
2018-05-02 15:35:44 +00:00
|
|
|
let build_dir = Path.relative Path.build_dir name in
|
2018-03-20 16:43:51 +00:00
|
|
|
let ocamlpath =
|
|
|
|
match
|
|
|
|
let var = "OCAMLPATH" in
|
|
|
|
match kind, findlib_toolchain with
|
|
|
|
| Default, None -> Env.get env var
|
|
|
|
| _ ->
|
|
|
|
(* If we are not in the default context, we can only use the
|
|
|
|
OCAMLPATH variable if it is specific to this build
|
|
|
|
context *)
|
|
|
|
(* CR-someday diml: maybe we should actually clear OCAMLPATH
|
|
|
|
in other build contexts *)
|
2018-03-29 15:58:41 +00:00
|
|
|
match Env.get env var, Env.get Env.initial var with
|
2018-03-20 16:43:51 +00:00
|
|
|
| None , None -> None
|
|
|
|
| Some s, None -> Some s
|
|
|
|
| None , Some _ -> None
|
|
|
|
| Some x, Some y -> Option.some_if (x <> y) x
|
|
|
|
with
|
|
|
|
| None -> []
|
|
|
|
| Some s -> Bin.parse_path s ~sep:ocamlpath_sep
|
|
|
|
in
|
2018-02-06 14:39:03 +00:00
|
|
|
let findlib_path () =
|
2018-03-06 14:56:24 +00:00
|
|
|
match kind, findlib_toolchain, Setup.library_path with
|
|
|
|
| Default, None, Some l ->
|
2018-06-02 11:14:44 +00:00
|
|
|
Fiber.return
|
|
|
|
(ocamlpath @ List.map l ~f:Path.of_filename_relative_to_initial_cwd)
|
2018-03-06 14:56:24 +00:00
|
|
|
| _ ->
|
2017-12-21 11:54:00 +00:00
|
|
|
(* If ocamlfind is present, it has precedence over everything else. *)
|
|
|
|
match which "ocamlfind" with
|
|
|
|
| Some fn ->
|
|
|
|
let args =
|
|
|
|
let args = ["printconf"; "path"] in
|
|
|
|
match findlib_toolchain with
|
|
|
|
| None -> args
|
|
|
|
| Some s -> "-toolchain" :: s :: args
|
|
|
|
in
|
2018-04-25 09:30:18 +00:00
|
|
|
Process.run_capture_lines ~env Strict fn args
|
2018-03-20 16:43:51 +00:00
|
|
|
>>| fun l ->
|
|
|
|
(* Don't prepend the contents of [OCAMLPATH] since findlib
|
|
|
|
does it already *)
|
2018-06-02 11:14:44 +00:00
|
|
|
List.map l ~f:Path.of_filename_relative_to_initial_cwd
|
2017-07-25 16:07:24 +00:00
|
|
|
| None ->
|
2017-12-21 11:54:00 +00:00
|
|
|
(* If there no ocamlfind in the PATH, check if we have opam
|
|
|
|
and assume a standard opam setup *)
|
|
|
|
opam_config_var ~env ~cache:opam_var_cache "lib"
|
|
|
|
>>| function
|
2018-06-02 11:14:44 +00:00
|
|
|
| Some s -> ocamlpath @ [Path.of_filename_relative_to_initial_cwd s]
|
2017-12-21 11:54:00 +00:00
|
|
|
| None ->
|
2018-03-06 14:56:24 +00:00
|
|
|
(* If neither opam neither ocamlfind are present, assume
|
|
|
|
that libraries are [dir ^ "/../lib"] *)
|
2018-05-08 16:56:58 +00:00
|
|
|
ocamlpath @ [Path.relative (Path.parent_exn dir) "lib"]
|
2017-12-21 11:54:00 +00:00
|
|
|
in
|
2018-03-06 17:48:06 +00:00
|
|
|
let ocaml_config_ok_exn = function
|
|
|
|
| Ok x -> x
|
|
|
|
| Error msg ->
|
|
|
|
die "Failed to parse the output of '%s -config':@\n\
|
|
|
|
%s"
|
|
|
|
(Path.to_string ocamlc) msg
|
|
|
|
in
|
2018-02-06 14:39:03 +00:00
|
|
|
Fiber.fork_and_join
|
2017-12-21 11:54:00 +00:00
|
|
|
findlib_path
|
2018-03-06 12:18:21 +00:00
|
|
|
(fun () ->
|
2018-04-25 09:30:18 +00:00
|
|
|
Process.run_capture_lines ~env Strict ocamlc ["-config"]
|
2018-03-06 17:48:06 +00:00
|
|
|
>>| fun lines ->
|
|
|
|
let open Result.O in
|
|
|
|
ocaml_config_ok_exn
|
2018-03-06 17:52:28 +00:00
|
|
|
(Ocaml_config.Vars.of_lines lines >>= Ocaml_config.make))
|
|
|
|
>>= fun (findlib_path, ocfg) ->
|
2018-03-12 11:40:53 +00:00
|
|
|
let version = Ocaml_config.version ocfg in
|
2018-03-12 03:44:04 +00:00
|
|
|
let env =
|
2018-03-12 11:40:53 +00:00
|
|
|
(* See comment in ansi_color.ml for setup_env_for_colors. For
|
|
|
|
OCaml < 4.05, OCAML_COLOR is not supported so we use
|
|
|
|
OCAMLPARAM. OCaml 4.02 doesn't support 'color' in OCAMLPARAM,
|
|
|
|
so we just don't force colors with 4.02. *)
|
2017-12-21 11:54:00 +00:00
|
|
|
if !Clflags.capture_outputs
|
2018-02-25 16:35:25 +00:00
|
|
|
&& Lazy.force Colors.stderr_supports_colors
|
2018-02-08 10:12:46 +00:00
|
|
|
&& version >= (4, 03, 0)
|
|
|
|
&& version < (4, 05, 0) then
|
2017-12-21 11:54:00 +00:00
|
|
|
let value =
|
2018-03-11 04:17:09 +00:00
|
|
|
match Env.get env "OCAMLPARAM" with
|
2017-12-21 11:54:00 +00:00
|
|
|
| None -> "color=always,_"
|
|
|
|
| Some s -> "color=always," ^ s
|
|
|
|
in
|
2018-03-12 03:44:04 +00:00
|
|
|
Env.add env ~var:"OCAMLPARAM" ~value
|
2017-12-21 11:54:00 +00:00
|
|
|
else
|
2018-03-12 03:44:04 +00:00
|
|
|
env
|
2017-12-21 11:54:00 +00:00
|
|
|
in
|
2018-03-15 16:36:55 +00:00
|
|
|
let env =
|
|
|
|
let cwd = Sys.getcwd () in
|
2018-03-19 23:22:58 +00:00
|
|
|
let extend_var var ?(path_sep=Bin.path_sep) v =
|
2018-03-15 16:36:55 +00:00
|
|
|
let v = Filename.concat cwd (Path.to_string v) in
|
|
|
|
match Env.get env var with
|
|
|
|
| None -> (var, v)
|
2018-03-19 23:22:58 +00:00
|
|
|
| Some prev -> (var, sprintf "%s%c%s" v path_sep prev)
|
2018-03-15 16:36:55 +00:00
|
|
|
in
|
|
|
|
let vars =
|
|
|
|
[ extend_var "CAML_LD_LIBRARY_PATH"
|
|
|
|
(Path.relative
|
|
|
|
(Config.local_install_dir ~context:name)
|
|
|
|
"lib/stublibs")
|
2018-03-19 23:22:58 +00:00
|
|
|
; extend_var "OCAMLPATH" ~path_sep:ocamlpath_sep
|
2018-03-15 16:36:55 +00:00
|
|
|
(Path.relative
|
|
|
|
(Config.local_install_dir ~context:name)
|
|
|
|
"lib")
|
|
|
|
; extend_var "MANPATH"
|
|
|
|
(Config.local_install_man_dir ~context:name)
|
2018-04-11 14:26:51 +00:00
|
|
|
; "DUNE_CONFIGURATOR", (Path.to_string ocamlc)
|
2018-03-15 16:36:55 +00:00
|
|
|
]
|
|
|
|
in
|
|
|
|
Env.extend env ~vars:(Env.Map.of_list_exn vars)
|
2018-03-22 14:44:21 +00:00
|
|
|
|> Env.update ~var:"PATH" ~f:(fun _ ->
|
|
|
|
match host with
|
|
|
|
| None ->
|
|
|
|
let _key, path =
|
|
|
|
extend_var "PATH" (Config.local_install_bin_dir ~context:name) in
|
|
|
|
Some path
|
|
|
|
| Some host ->
|
|
|
|
Env.get host.env "PATH"
|
|
|
|
)
|
2018-04-30 17:13:50 +00:00
|
|
|
|> Env.extend_env (
|
|
|
|
Option.value ~default:Env.empty
|
|
|
|
(Option.map findlib_config ~f:Findlib.Config.env)
|
|
|
|
)
|
2018-03-15 16:36:55 +00:00
|
|
|
in
|
2018-03-06 17:52:28 +00:00
|
|
|
let stdlib_dir = Path.of_string (Ocaml_config.standard_library ocfg) in
|
|
|
|
let natdynlink_supported = Ocaml_config.natdynlink_supported ocfg in
|
|
|
|
let version = Ocaml_config.version ocfg in
|
|
|
|
let version_string = Ocaml_config.version_string ocfg in
|
|
|
|
let arch_sixtyfour = Ocaml_config.word_size ocfg = 64 in
|
2018-02-06 14:39:03 +00:00
|
|
|
Fiber.return
|
2017-12-21 11:54:00 +00:00
|
|
|
{ name
|
|
|
|
; implicit
|
|
|
|
; kind
|
2018-05-04 15:49:25 +00:00
|
|
|
; profile
|
2017-12-21 11:54:00 +00:00
|
|
|
; merlin
|
|
|
|
; for_host = host
|
|
|
|
; build_dir
|
|
|
|
; path
|
2018-03-10 14:15:02 +00:00
|
|
|
; toplevel_path =
|
2018-06-02 11:14:44 +00:00
|
|
|
Option.map (Env.get env "OCAML_TOPLEVEL_PATH")
|
|
|
|
~f:Path.of_filename_relative_to_initial_cwd
|
2017-12-21 11:54:00 +00:00
|
|
|
|
|
|
|
; ocaml_bin = dir
|
|
|
|
; ocaml = (match which "ocaml" with Some p -> p | None -> prog_not_found_in_path "ocaml")
|
|
|
|
; ocamlc
|
|
|
|
; ocamlopt = get_ocaml_tool "ocamlopt"
|
|
|
|
; ocamldep = get_ocaml_tool_exn "ocamldep"
|
|
|
|
; ocamlmklib = get_ocaml_tool_exn "ocamlmklib"
|
|
|
|
|
|
|
|
; env
|
|
|
|
; findlib = Findlib.create ~stdlib_dir ~path:findlib_path
|
|
|
|
; findlib_toolchain
|
|
|
|
; arch_sixtyfour
|
|
|
|
|
|
|
|
; opam_var_cache
|
|
|
|
|
|
|
|
; natdynlink_supported
|
|
|
|
|
|
|
|
; stdlib_dir
|
2018-03-06 17:52:28 +00:00
|
|
|
; ocaml_config = ocfg
|
2018-02-08 10:12:46 +00:00
|
|
|
; version_string
|
2017-12-21 11:54:00 +00:00
|
|
|
; version
|
2018-03-06 17:52:28 +00:00
|
|
|
; ccomp_type = Ocaml_config.ccomp_type ocfg
|
|
|
|
; c_compiler = Ocaml_config.c_compiler ocfg
|
|
|
|
; ocamlc_cflags = Ocaml_config.ocamlc_cflags ocfg
|
|
|
|
; ocamlopt_cflags = Ocaml_config.ocamlopt_cflags ocfg
|
|
|
|
; bytecomp_c_libraries = Ocaml_config.bytecomp_c_libraries ocfg
|
|
|
|
; native_c_libraries = Ocaml_config.native_c_libraries ocfg
|
|
|
|
; cc_profile = Ocaml_config.cc_profile ocfg
|
|
|
|
; architecture = Ocaml_config.architecture ocfg
|
|
|
|
; system = Ocaml_config.system ocfg
|
|
|
|
; ext_obj = Ocaml_config.ext_obj ocfg
|
|
|
|
; ext_asm = Ocaml_config.ext_asm ocfg
|
|
|
|
; ext_lib = Ocaml_config.ext_lib ocfg
|
|
|
|
; ext_dll = Ocaml_config.ext_dll ocfg
|
|
|
|
; ext_exe = Ocaml_config.ext_exe ocfg
|
|
|
|
; os_type = Ocaml_config.os_type ocfg
|
|
|
|
; default_executable_name = Ocaml_config.default_executable_name ocfg
|
|
|
|
; host = Ocaml_config.host ocfg
|
|
|
|
; target = Ocaml_config.target ocfg
|
|
|
|
; flambda = Ocaml_config.flambda ocfg
|
|
|
|
; exec_magic_number = Ocaml_config.exec_magic_number ocfg
|
|
|
|
; cmi_magic_number = Ocaml_config.cmi_magic_number ocfg
|
|
|
|
; cmo_magic_number = Ocaml_config.cmo_magic_number ocfg
|
|
|
|
; cma_magic_number = Ocaml_config.cma_magic_number ocfg
|
|
|
|
; cmx_magic_number = Ocaml_config.cmx_magic_number ocfg
|
|
|
|
; cmxa_magic_number = Ocaml_config.cmxa_magic_number ocfg
|
|
|
|
; ast_impl_magic_number = Ocaml_config.ast_impl_magic_number ocfg
|
|
|
|
; ast_intf_magic_number = Ocaml_config.ast_intf_magic_number ocfg
|
|
|
|
; cmxs_magic_number = Ocaml_config.cmxs_magic_number ocfg
|
|
|
|
; cmt_magic_number = Ocaml_config.cmt_magic_number ocfg
|
2017-12-21 11:54:00 +00:00
|
|
|
|
|
|
|
; which_cache
|
|
|
|
}
|
2017-11-03 13:44:41 +00:00
|
|
|
in
|
2017-12-21 11:54:00 +00:00
|
|
|
|
|
|
|
let implicit = not (List.mem ~set:targets Workspace.Context.Target.Native) in
|
|
|
|
create_one () ~implicit ~name ~merlin >>= fun native ->
|
2018-02-06 14:39:03 +00:00
|
|
|
Fiber.parallel_map targets ~f:(function
|
|
|
|
| Native -> Fiber.return None
|
|
|
|
| Named findlib_toolchain ->
|
|
|
|
let name = sprintf "%s.%s" name findlib_toolchain in
|
|
|
|
create_one () ~implicit:false ~name ~findlib_toolchain ~host:native
|
|
|
|
~merlin:false
|
|
|
|
>>| fun x -> Some x)
|
|
|
|
>>| fun others ->
|
|
|
|
native :: List.filter_map others ~f:(fun x -> x)
|
2016-12-02 13:54:32 +00:00
|
|
|
|
2017-02-24 15:41:52 +00:00
|
|
|
let opam_config_var t var = opam_config_var ~env:t.env ~cache:t.opam_var_cache var
|
|
|
|
|
2018-03-29 15:58:41 +00:00
|
|
|
let default ?(merlin=true) ~env ~targets () =
|
|
|
|
create ~kind:Default ~path:Bin.path ~env ~name:"default" ~merlin ~targets ()
|
2016-12-02 13:54:32 +00:00
|
|
|
|
2018-05-04 15:49:25 +00:00
|
|
|
let create_for_opam ?root ~env ~targets ~profile ~switch ~name
|
|
|
|
?(merlin=false) () =
|
2016-12-02 13:54:32 +00:00
|
|
|
match Bin.opam with
|
2017-03-31 16:31:55 +00:00
|
|
|
| None -> Utils.program_not_found "opam"
|
2016-12-02 13:54:32 +00:00
|
|
|
| Some fn ->
|
|
|
|
(match root with
|
2018-02-06 14:39:03 +00:00
|
|
|
| Some root -> Fiber.return root
|
2016-12-02 13:54:32 +00:00
|
|
|
| None ->
|
2018-04-25 09:30:18 +00:00
|
|
|
Process.run_capture_line Strict ~env fn ["config"; "var"; "root"])
|
2016-12-02 13:54:32 +00:00
|
|
|
>>= fun root ->
|
2018-04-25 09:30:18 +00:00
|
|
|
Process.run_capture ~env Strict fn
|
2016-12-02 13:54:32 +00:00
|
|
|
["config"; "env"; "--root"; root; "--switch"; switch; "--sexp"]
|
|
|
|
>>= fun s ->
|
|
|
|
let vars =
|
2017-12-12 10:16:17 +00:00
|
|
|
Usexp.parse_string ~fname:"<opam output>" ~mode:Single s
|
2018-06-19 10:53:16 +00:00
|
|
|
|> Sexp.Of_sexp.(parse (list (pair string string)) Univ_map.empty)
|
2018-03-10 13:33:59 +00:00
|
|
|
|> Env.Map.of_list_multi
|
|
|
|
|> Env.Map.mapi ~f:(fun var values ->
|
2017-03-31 16:44:03 +00:00
|
|
|
match List.rev values with
|
|
|
|
| [] -> assert false
|
|
|
|
| [x] -> x
|
|
|
|
| x :: _ ->
|
|
|
|
Format.eprintf
|
|
|
|
"@{<warning>Warning@}: variable %S present multiple times in the output of:\n\
|
|
|
|
@{<details>%s@}@."
|
|
|
|
var
|
|
|
|
(String.concat ~sep:" "
|
|
|
|
(List.map ~f:quote_for_shell
|
|
|
|
[Path.to_string fn; "config"; "env"; "--root"; root;
|
|
|
|
"--switch"; switch; "--sexp"]));
|
|
|
|
x)
|
2016-12-02 13:54:32 +00:00
|
|
|
in
|
|
|
|
let path =
|
2018-03-10 13:33:59 +00:00
|
|
|
match Env.Map.find vars "PATH" with
|
2018-03-19 23:22:58 +00:00
|
|
|
| None -> Bin.path
|
2016-12-02 13:54:32 +00:00
|
|
|
| Some s -> Bin.parse_path s
|
|
|
|
in
|
2018-03-29 15:58:41 +00:00
|
|
|
let env = Env.extend env ~vars in
|
2018-05-04 15:49:25 +00:00
|
|
|
create ~kind:(Opam { root; switch }) ~profile ~targets ~path ~env ~name
|
|
|
|
~merlin ()
|
2017-12-21 11:54:00 +00:00
|
|
|
|
2018-03-29 15:58:41 +00:00
|
|
|
let create ?merlin ~env def =
|
2017-12-21 11:54:00 +00:00
|
|
|
match (def : Workspace.Context.t) with
|
2018-06-29 21:54:33 +00:00
|
|
|
| Default { targets; profile; _ } -> default ~env ~profile ~targets ?merlin ()
|
2018-05-04 15:49:25 +00:00
|
|
|
| Opam { name; switch; root; targets; profile; _ } ->
|
|
|
|
create_for_opam ?root ~env ~profile ~switch ~name ?merlin ~targets ()
|
2016-12-02 13:54:32 +00:00
|
|
|
|
2017-03-01 11:04:32 +00:00
|
|
|
let which t s = which ~cache:t.which_cache ~path:t.path s
|
2017-02-24 15:41:52 +00:00
|
|
|
|
|
|
|
let install_prefix t =
|
|
|
|
opam_config_var t "prefix" >>| function
|
2018-06-02 11:14:44 +00:00
|
|
|
| Some x -> Path.of_filename_relative_to_initial_cwd x
|
2018-05-08 16:56:58 +00:00
|
|
|
| None -> Path.parent_exn t.ocaml_bin
|
2017-03-01 12:09:57 +00:00
|
|
|
|
2017-07-05 13:10:41 +00:00
|
|
|
let install_ocaml_libdir t =
|
2018-03-06 14:56:24 +00:00
|
|
|
match t.kind, t.findlib_toolchain, Setup.library_destdir with
|
|
|
|
| Default, None, Some d ->
|
2018-06-02 11:14:44 +00:00
|
|
|
Fiber.return (Some (Path.of_filename_relative_to_initial_cwd d))
|
2018-03-06 14:56:24 +00:00
|
|
|
| _ ->
|
|
|
|
(* If ocamlfind is present, it has precedence over everything else. *)
|
|
|
|
match which t "ocamlfind" with
|
|
|
|
| Some fn ->
|
2018-04-25 09:30:18 +00:00
|
|
|
(Process.run_capture_line ~env:t.env Strict fn ["printconf"; "destdir"]
|
2018-03-06 14:56:24 +00:00
|
|
|
>>| fun s ->
|
2018-06-02 11:14:44 +00:00
|
|
|
Some (Path.of_filename_relative_to_initial_cwd s))
|
2018-03-06 14:56:24 +00:00
|
|
|
| None ->
|
|
|
|
Fiber.return None
|
2017-03-01 12:09:57 +00:00
|
|
|
|
2017-04-28 09:40:09 +00:00
|
|
|
let compiler t (mode : Mode.t) =
|
|
|
|
match mode with
|
|
|
|
| Byte -> Some t.ocamlc
|
|
|
|
| Native -> t.ocamlopt
|
|
|
|
|
|
|
|
let best_mode t : Mode.t =
|
|
|
|
match t.ocamlopt with
|
|
|
|
| Some _ -> Native
|
|
|
|
| None -> Byte
|
2017-06-05 10:40:27 +00:00
|
|
|
|
|
|
|
let cc_g (ctx : t) =
|
|
|
|
if !Clflags.g && ctx.ccomp_type <> "msvc" then
|
|
|
|
["-g"]
|
|
|
|
else
|
|
|
|
[]
|