From dfdb6c09f4323972825e5cc0b3c2e39ff3889c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Dimino?= Date: Tue, 6 Mar 2018 14:56:24 +0000 Subject: [PATCH] Allow to set the library path at configure time (#575) This allow to drop the dependency on ocamlfind --- .gitignore | 1 + CHANGES.md | 3 +++ Makefile | 3 +++ configure | 2 ++ configure.ml | 40 +++++++++++++++++++++++++++++++ jbuilder.opam | 10 +------- src/context.ml | 55 ++++++++++++++++++++++++------------------- src/context.mli | 6 +---- src/jbuild | 5 ++++ src/main.ml | 9 ++++--- src/setup.boot.ml | 2 ++ src/setup.defaults.ml | 2 ++ src/setup.mli | 12 ++++++++++ 13 files changed, 107 insertions(+), 43 deletions(-) create mode 100755 configure create mode 100644 configure.ml create mode 100644 src/setup.boot.ml create mode 100644 src/setup.defaults.ml create mode 100644 src/setup.mli diff --git a/.gitignore b/.gitignore index 4a81f6524f0..60f5ad5d5fa 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ bootstrap.cmi bootstrap.cmo bootstrap.exe Makefile.dev +src/setup.ml \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index 7fac809ee8c..9cc01005e10 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,9 @@ next compiler is not installed but still has a META file (#574, fixes #563) +- Do not depend on ocamlfind. Instead, hard-code the library path when + installing from opam (#575) + - Reduce interleaving in the scheduler in an attempt to make Jbuilder keep file descriptors open for less long (#586) diff --git a/Makefile b/Makefile index 2c7347d7aa2..0441e4e6cbc 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,9 @@ clean: $(BIN) clean rm -f ./boot.exe $(wildcard ./bootstrap.cmi ./bootstrap.cmo ./bootstrap.exe) +distclean: clean + rm -f src/setup.ml + doc: cd doc && sphinx-build . _build diff --git a/configure b/configure new file mode 100755 index 00000000000..eb093a5536f --- /dev/null +++ b/configure @@ -0,0 +1,2 @@ +#!/bin/sh +exec ocaml configure.ml "$@" diff --git a/configure.ml b/configure.ml new file mode 100644 index 00000000000..4e2cbcb0507 --- /dev/null +++ b/configure.ml @@ -0,0 +1,40 @@ +#!/usr/bin/env ocaml + +open StdLabels +open Printf + +let list f l = sprintf "[%s]" (String.concat ~sep:"; " (List.map l ~f)) +let string s = sprintf "%S" s +let option f = function + | None -> "None" + | Some x -> sprintf "Some %s" (f x) + +let () = + let bad fmt = ksprintf (fun s -> raise (Arg.Bad s)) fmt in + let library_path = ref None in + let library_destdir = ref None in + let set_libdir s = + let dir = + if Filename.is_relative s then + Filename.concat (Sys.getcwd ()) s + else + s + in + library_path := Some [dir]; + library_destdir := Some dir + in + let args = + [ "--libdir", Arg.String set_libdir, + "DIR where installed libraries are for the default build context" + ] + in + let anon s = + bad "Don't know what to do with %s" s + in + Arg.parse (Arg.align args) + anon "Usage: ocaml configure.ml [OPTRIONS]]\nOptions are:"; + let oc = open_out "src/setup.ml" in + let pr fmt = fprintf oc (fmt ^^ "\n") in + pr "let library_path = %s" (option (list string) !library_path); + pr "let library_destdir = %s" (option string !library_destdir); + close_out oc diff --git a/jbuilder.opam b/jbuilder.opam index 84d257c5538..7d6efcc19e4 100644 --- a/jbuilder.opam +++ b/jbuilder.opam @@ -6,17 +6,9 @@ bug-reports: "https://github.com/ocaml/dune/issues" dev-repo: "https://github.com/ocaml/dune.git" license: "Apache-2.0" build: [ + ["ocaml" "configure.ml" "--libdir" lib] ["ocaml" "bootstrap.ml"] ["./boot.exe" "--subst"] {pinned} ["./boot.exe" "-j" jobs] ] -depends: [ - # ocamlfind is not mandatory to build packages using - # jbuilder. However if it is present jbuilder will use it. Making - # it a hard-dependency avoids problems when there is a previous - # ocamlfind in the PATH. We make it a "build" depepdency even though - # it is only a runtime dependency so that reinstalling ocamlfind - # doesn't resintall jbuilder - "ocamlfind" {build} -] available: [ ocaml-version >= "4.02.3" ] diff --git a/src/context.ml b/src/context.ml index 094c556ed22..823819131b8 100644 --- a/src/context.ml +++ b/src/context.ml @@ -136,7 +136,8 @@ let opam_config_var ~env ~cache var = match Bin.opam with | None -> Fiber.return None | Some fn -> - Process.run_capture (Accept All) (Path.to_string fn) ~env ["config"; "var"; var] + Process.run_capture (Accept All) (Path.to_string fn) ~env + ["config"; "var"; var] >>| function | Ok s -> let s = String.trim s in @@ -180,7 +181,7 @@ let extend_env ~vars ~env = |> Array.of_list let create ~(kind : Kind.t) ~path ~base_env ~env_extra ~name ~merlin - ~use_findlib ~targets () = + ~targets () = let env = extend_env ~env:base_env ~vars:env_extra in let opam_var_cache = Hashtbl.create 128 in (match kind with @@ -251,7 +252,10 @@ let create ~(kind : Kind.t) ~path ~base_env ~env_extra ~name ~merlin let build_dir = Path.of_string (sprintf "_build/%s" name) in let findlib_path () = - if use_findlib then + match kind, findlib_toolchain, Setup.library_path with + | Default, None, Some l -> + Fiber.return (List.map l ~f:Path.absolute) + | _ -> (* If ocamlfind is present, it has precedence over everything else. *) match which "ocamlfind" with | Some fn -> @@ -270,11 +274,9 @@ let create ~(kind : Kind.t) ~path ~base_env ~env_extra ~name ~merlin >>| function | Some s -> [Path.absolute s] | None -> - (* If neither opam neither ocamlfind are present, assume that libraries are - [dir ^ "/../lib"] *) + (* If neither opam neither ocamlfind are present, assume + that libraries are [dir ^ "/../lib"] *) [Path.relative (Path.parent dir) "lib"] - else - Fiber.return [] in Fiber.fork_and_join findlib_path @@ -282,9 +284,10 @@ let create ~(kind : Kind.t) ~path ~base_env ~env_extra ~name ~merlin >>= fun (findlib_path, ocamlc_config) -> let version = Ocamlc_config.version ocamlc_config in let env, env_extra = - (* 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. *) + (* 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. *) if !Clflags.capture_outputs && Lazy.force Colors.stderr_supports_colors && version >= (4, 03, 0) @@ -397,7 +400,7 @@ let initial_env = lazy ( Lazy.force Colors.setup_env_for_colors; Unix.environment ()) -let default ?(merlin=true) ?(use_findlib=true) ~targets () = +let default ?(merlin=true) ~targets () = let env = Lazy.force initial_env in let path = match get_env env "PATH" with @@ -405,7 +408,7 @@ let default ?(merlin=true) ?(use_findlib=true) ~targets () = | None -> [] in create ~kind:Default ~path ~base_env:env ~env_extra:Env_var_map.empty - ~name:"default" ~merlin ~use_findlib ~targets () + ~name:"default" ~merlin ~targets () let create_for_opam ?root ~targets ~switch ~name ?(merlin=false) () = match Bin.opam with @@ -445,11 +448,11 @@ let create_for_opam ?root ~targets ~switch ~name ?(merlin=false) () = in let env = Lazy.force initial_env in create ~kind:(Opam { root; switch }) ~targets - ~path ~base_env:env ~env_extra:vars ~name ~merlin ~use_findlib:true () + ~path ~base_env:env ~env_extra:vars ~name ~merlin () -let create ?use_findlib ?merlin def = +let create ?merlin def = match (def : Workspace.Context.t) with - | Default targets -> default ~targets ?merlin ?use_findlib () + | Default targets -> default ~targets ?merlin () | Opam { name; switch; root; targets; _ } -> create_for_opam ?root ~switch ~name ?merlin ~targets () @@ -461,15 +464,19 @@ let install_prefix t = | None -> Path.parent t.ocaml_bin let install_ocaml_libdir t = - (* If ocamlfind is present, it has precedence over everything else. *) - match which t "ocamlfind" with - | Some fn -> - (Process.run_capture_line ~env:t.env Strict - (Path.to_string fn) ["printconf"; "destdir"] - >>| fun s -> - Some (Path.absolute s)) - | None -> - Fiber.return None + match t.kind, t.findlib_toolchain, Setup.library_destdir with + | Default, None, Some d -> + Fiber.return (Some (Path.absolute d)) + | _ -> + (* If ocamlfind is present, it has precedence over everything else. *) + match which t "ocamlfind" with + | Some fn -> + (Process.run_capture_line ~env:t.env Strict + (Path.to_string fn) ["printconf"; "destdir"] + >>| fun s -> + Some (Path.absolute s)) + | None -> + Fiber.return None (* CR-someday jdimino: maybe we should just do this for [t.env] directly? *) let env_for_exec t = diff --git a/src/context.mli b/src/context.mli index 6faad68d66b..1c9616bea2c 100644 --- a/src/context.mli +++ b/src/context.mli @@ -129,12 +129,8 @@ val sexp_of_t : t -> Sexp.t (** Compare the context names *) val compare : t -> t -> Ordering.t -(** If [use_findlib] is [false], don't try to guess the library search path with opam or - ocamlfind. This is only for building jbuilder itself, so that its build is completely - independent of the user setup. *) val create - : ?use_findlib:bool - -> ?merlin:bool + : ?merlin:bool -> Workspace.Context.t -> t list Fiber.t diff --git a/src/jbuild b/src/jbuild index cd1e93594a6..897e56fa93c 100644 --- a/src/jbuild +++ b/src/jbuild @@ -13,3 +13,8 @@ (synopsis "Internal Jbuilder library, do not use!"))) (ocamllex (meta_lexer glob_lexer)) + +(rule + ((targets (setup.ml)) + (mode fallback) + (action (copy# setup.defaults.ml setup.ml)))) diff --git a/src/main.ml b/src/main.ml index 6e550dc844a..1ec8f4ddd5e 100644 --- a/src/main.ml +++ b/src/main.ml @@ -21,7 +21,6 @@ let package_install_file { packages; _ } pkg = let setup ?(log=Log.no_log) ?filter_out_optional_stanzas_with_missing_deps ?workspace ?(workspace_file="jbuild-workspace") - ?(use_findlib=true) ?only_packages ?extra_ignored_subtrees ?x @@ -56,11 +55,12 @@ let setup ?(log=Log.no_log) Fiber.parallel_map workspace.contexts ~f:(fun ctx_def -> let name = Workspace.Context.name ctx_def in - Context.create ctx_def ~merlin:(workspace.merlin_context = Some name) ~use_findlib) + Context.create ctx_def ~merlin:(workspace.merlin_context = Some name)) >>= fun contexts -> let contexts = List.concat contexts in List.iter contexts ~f:(fun (ctx : Context.t) -> - Log.infof log "@[<1>Jbuilder context:@,%a@]@." Sexp.pp (Context.sexp_of_t ctx)); + Log.infof log "@[<1>Jbuilder context:@,%a@]@." Sexp.pp + (Context.sexp_of_t ctx)); let rule_done = ref 0 in let rule_total = ref 0 in let gen_status_line () = @@ -168,7 +168,6 @@ let bootstrap () = Scheduler.go ~log ~config (setup ~log ~workspace:{ merlin_context = Some "default" ; contexts = [Default [Native]] } - ~use_findlib:false ~extra_ignored_subtrees:ignored_during_bootstrap () >>= fun { build_system = bs; _ } -> @@ -183,7 +182,7 @@ let bootstrap () = Report_error.report exn; exit 1 -let setup = setup ~use_findlib:true ~extra_ignored_subtrees:Path.Set.empty +let setup = setup ~extra_ignored_subtrees:Path.Set.empty let find_context_exn t ~name = match List.find t.contexts ~f:(fun c -> c.name = name) with diff --git a/src/setup.boot.ml b/src/setup.boot.ml new file mode 100644 index 00000000000..6321eb84a18 --- /dev/null +++ b/src/setup.boot.ml @@ -0,0 +1,2 @@ +let library_path = Some [] +let library_destdir = None diff --git a/src/setup.defaults.ml b/src/setup.defaults.ml new file mode 100644 index 00000000000..d810c44e7b9 --- /dev/null +++ b/src/setup.defaults.ml @@ -0,0 +1,2 @@ +let library_path = None +let library_destdir = None diff --git a/src/setup.mli b/src/setup.mli new file mode 100644 index 00000000000..52445052f0b --- /dev/null +++ b/src/setup.mli @@ -0,0 +1,12 @@ +(** Setup of Jbuilder *) + +(** These parameters are set by [ocaml configure.ml] or copied from + [setup.defaults.ml]. During bootstrap, values from [setup.boot.ml] + are used *) + +(** Where to find installed libraries for the default context. If + [None], auto-detect it using standard tools such as [ocamlfind]. *) +val library_path : string list option + +(** Where to install libraries for the default context. *) +val library_destdir : string option