Simplify a bit the rules for installation of library files

This commit is contained in:
Jeremie Dimino 2017-07-25 17:07:24 +01:00
parent 44a15bcd24
commit cfd43d5282
4 changed files with 76 additions and 69 deletions

View File

@ -685,13 +685,10 @@ let get_prefix context ~from_command_line =
| Some p -> Future.return (Path.of_string p) | Some p -> Future.return (Path.of_string p)
| None -> Context.install_prefix context | None -> Context.install_prefix context
let get_libdir context ~libdir_from_command_line ~prefix_from_command_line = let get_libdir context ~libdir_from_command_line =
match libdir_from_command_line with match libdir_from_command_line with
| Some p -> Future.return (Path.of_string p) | Some p -> Future.return (Some (Path.of_string p))
| None -> | None -> Context.install_ocaml_libdir context
match prefix_from_command_line with
| Some p -> Future.return (Path.relative (Path.of_string p) "lib")
| None -> Context.install_ocaml_libdir context
let install_uninstall ~what = let install_uninstall ~what =
let doc = let doc =
@ -730,25 +727,32 @@ let install_uninstall ~what =
end; end;
(match setup.contexts, prefix_from_command_line, libdir_from_command_line with (match setup.contexts, prefix_from_command_line, libdir_from_command_line with
| _ :: _ :: _, Some _, _ | _ :: _ :: _, _, Some _ -> | _ :: _ :: _, Some _, _ | _ :: _ :: _, _, Some _ ->
die "Cannot specify --prefix or --libdir when installing into multiple contexts!" die "Cannot specify --prefix or --libdir when installing \
into multiple contexts!"
| _ -> ()); | _ -> ());
let module CMap = Map.Make(Context) in let module CMap = Map.Make(Context) in
let install_files_by_context = CMap.of_alist_multi install_files |> CMap.bindings in let install_files_by_context =
CMap.of_alist_multi install_files |> CMap.bindings
in
Future.all_unit Future.all_unit
(List.map install_files_by_context ~f:(fun (context, install_files) -> (List.map install_files_by_context ~f:(fun (context, install_files) ->
get_prefix context ~from_command_line:prefix_from_command_line >>= fun prefix -> get_prefix context ~from_command_line:prefix_from_command_line
get_libdir context ~libdir_from_command_line ~prefix_from_command_line >>= fun libdir -> >>= fun prefix ->
get_libdir context ~libdir_from_command_line
>>= fun libdir ->
Future.all_unit Future.all_unit
(List.map install_files ~f:(fun path -> (List.map install_files ~f:(fun path ->
let purpose = Future.Build_job install_files in let purpose = Future.Build_job install_files in
Future.run ~purpose Strict (Path.to_string opam_installer) Future.run ~purpose Strict (Path.to_string opam_installer)
[ sprintf "-%c" what.[0] ([ sprintf "-%c" what.[0]
; "--prefix" ; Path.to_string path
; Path.to_string prefix ; "--prefix"
; "--libdir" ; Path.to_string prefix
; Path.to_string libdir ] @
; Path.to_string path match libdir with
]))))) | None -> []
| Some p -> [ "--libdir"; Path.to_string p ]
))))))
in in
( Term.(const go ( Term.(const go
$ common $ common

View File

@ -248,29 +248,38 @@ to be able to use ``jbuilder install``.
Destination Destination
----------- -----------
The place where the build artifacts (except library files) are copied, usually referred as The place where the build artifacts are copied, usually referred as
**prefix**, is determined as follow for a given build context: **prefix**, is determined as follow for a given build context:
#. if an explicit ``--prefix <path>`` argument is passed, use this path #. if an explicit ``--prefix <path>`` argument is passed, use this path
#. if ``opam`` is present in the ``PATH``, use the output of ``opam config var #. if ``opam`` is present in the ``PATH`` and is configured, use the
prefix`` output of ``opam config var prefix``
#. otherwise, take the parent of the directory where ``ocamlc`` was found. #. otherwise, take the parent of the directory where ``ocamlc`` was found.
The place where the library files are copied, referred as As an exception to this rule, library files might be copied to a
**libdir**, is determined as follow for a given build context: different location. The reason for this is that they often need to be
copied to a particular location for the various build system used in
OCaml projects to find them and this location might be different from
``<prefix>/lib`` on some systems.
#. if an explicit ``--libdir <path>`` argument is passed, use this path Historically, the location where to store OCaml library files was
#. if an explicit ``--prefix <path>`` argument is passed, use ``<path>/lib`` configured through `findlib
#. if ``ocamlfind`` is present in the ``PATH``, use the output of <http://projects.camlcity.org/projects/findlib.html>`__ and the
``ocamlfind printconf destdir`` ``ocamlfind`` command line tool was used to both install these files
#. if ``opam`` is present in the ``PATH``, use the output of ``opam config var and locate them. Many Linux distributions or other packaging systems
lib`` are using this mechanism to setup where OCaml library files should be
#. otherwise, take the directory of the ocaml standard library copied.
As a result, if none of ``--libdir`` and ``--prefix`` is passed to
``jbuilder install`` and ``ocamlfind`` is present in the ``PATH``,
then library files will be copied to the directory reported by
``ocamlfind printconf destdir``. This ensures that ``jbuilder
install`` can be used without opam. When using opam, ``ocamlfind`` is
configured to point to the opam directory, so this rule makes no
difference.
Note that ``--prefix`` and ``--libdir`` are only supported if a single
Note that ``--prefix`` and ``--libdir`` are only supported if a single build context is in build context is in use.
use.
Workspace configuration Workspace configuration
======================= =======================

View File

@ -200,8 +200,31 @@ let create ~(kind : Kind.t) ~path ~base_env ~env_extra ~name ~merlin ~use_findli
Path.of_string (sprintf "_build/%s" name) Path.of_string (sprintf "_build/%s" name)
in in
let ocamlc_config_cmd = sprintf "%s -config" (Path.to_string ocamlc) in let ocamlc_config_cmd = sprintf "%s -config" (Path.to_string ocamlc) in
Future.run_capture_lines ~env Strict (Path.to_string ocamlc) ["-config"] let findlib_path =
>>= fun ocamlc_config -> if use_findlib then
(* If ocamlfind is present, it has precedence over everything else. *)
match which "ocamlfind" with
| Some fn ->
(Future.run_capture_lines ~env Strict
(Path.to_string fn) ["printconf"; "path"]
>>| List.map ~f:Path.absolute)
| None ->
(* If there no ocamlfind in the PATH, check if we have opam and assume a stan opam
setup *)
opam_config_var ~env ~cache:opam_var_cache "lib"
>>| function
| Some s -> [Path.absolute s]
| None ->
(* If neither opam neither ocamlfind are present, assume that libraries are
[dir ^ "/../lib"] *)
[Path.relative (Path.parent dir) "lib"]
else
return []
in
both
findlib_path
(Future.run_capture_lines ~env Strict (Path.to_string ocamlc) ["-config"])
>>= fun (findlib_path, ocamlc_config) ->
let ocamlc_config = let ocamlc_config =
List.map ocamlc_config ~f:(fun line -> List.map ocamlc_config ~f:(fun line ->
match String.index line ':' with match String.index line ':' with
@ -280,28 +303,6 @@ let create ~(kind : Kind.t) ~path ~base_env ~env_extra ~name ~merlin ~use_findli
let _, ocamlopt_cflags = split_prog (get "native_c_compiler") in let _, ocamlopt_cflags = split_prog (get "native_c_compiler") in
(c_compiler, ocamlc_cflags, ocamlopt_cflags) (c_compiler, ocamlc_cflags, ocamlopt_cflags)
in in
let findlib_path =
if use_findlib then
(* If ocamlfind is present, it has precedence over everything else. *)
match which "ocamlfind" with
| Some fn ->
(Future.run_capture_lines ~env Strict
(Path.to_string fn) ["printconf"; "path"]
>>| List.map ~f:Path.absolute)
| None ->
(* 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
| Some s -> [Path.absolute s]
| None ->
(* If neither opam neither ocamlfind are present, assume that libraries are in
the stdlib directory *)
[stdlib_dir]
else
return []
in
findlib_path >>= fun findlib_path ->
return return
{ name { name
; kind ; kind
@ -433,17 +434,10 @@ let install_ocaml_libdir t =
| Some fn -> | Some fn ->
(Future.run_capture_line ~env:t.env Strict (Future.run_capture_line ~env:t.env Strict
(Path.to_string fn) ["printconf"; "destdir"] (Path.to_string fn) ["printconf"; "destdir"]
>>| Path.absolute) >>| fun s ->
Some (Path.absolute s))
| None -> | None ->
(* If there no ocamlfind in the PATH, check if we have opam and assume a standard return None
opam setup *)
opam_config_var t "lib"
>>| function
| Some s -> Path.absolute s
| None ->
(* If neither opam neither ocamlfind are present use stdlib dir *)
t.stdlib_dir
(* CR-someday jdimino: maybe we should just do this for [t.env] directly? *) (* CR-someday jdimino: maybe we should just do this for [t.env] directly? *)
let env_for_exec t = let env_for_exec t =

View File

@ -144,7 +144,7 @@ val extend_env : vars:string Env_var_map.t -> env:string array -> string array
val opam_config_var : t -> string -> string option Future.t val opam_config_var : t -> string -> string option Future.t
val install_prefix : t -> Path.t Future.t val install_prefix : t -> Path.t Future.t
val install_ocaml_libdir : t -> Path.t Future.t val install_ocaml_libdir : t -> Path.t option Future.t
val env_for_exec : t -> string array val env_for_exec : t -> string array