Allow to set the library path at configure time (#575)

This allow to drop the dependency on ocamlfind
This commit is contained in:
Jérémie Dimino 2018-03-06 14:56:24 +00:00 committed by GitHub
parent 2acbc72f76
commit dfdb6c09f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 107 additions and 43 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@ bootstrap.cmi
bootstrap.cmo
bootstrap.exe
Makefile.dev
src/setup.ml

View File

@ -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)

View File

@ -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

2
configure vendored Executable file
View File

@ -0,0 +1,2 @@
#!/bin/sh
exec ocaml configure.ml "$@"

40
configure.ml Normal file
View File

@ -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

View File

@ -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" ]

View File

@ -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 =

View File

@ -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

View File

@ -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))))

View File

@ -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

2
src/setup.boot.ml Normal file
View File

@ -0,0 +1,2 @@
let library_path = Some []
let library_destdir = None

2
src/setup.defaults.ml Normal file
View File

@ -0,0 +1,2 @@
let library_path = None
let library_destdir = None

12
src/setup.mli Normal file
View File

@ -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