From cfd43d5282c2d249ea7f23e62edfda11ff8f9f86 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Tue, 25 Jul 2017 17:07:24 +0100 Subject: [PATCH] Simplify a bit the rules for installation of library files --- bin/main.ml | 42 ++++++++++++++++++--------------- doc/usage.rst | 39 +++++++++++++++++++------------ src/context.ml | 62 ++++++++++++++++++++++--------------------------- src/context.mli | 2 +- 4 files changed, 76 insertions(+), 69 deletions(-) diff --git a/bin/main.ml b/bin/main.ml index 5d7161f3..4f4d3c4c 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -685,13 +685,10 @@ let get_prefix context ~from_command_line = | Some p -> Future.return (Path.of_string p) | 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 - | Some p -> Future.return (Path.of_string p) - | None -> - match prefix_from_command_line with - | Some p -> Future.return (Path.relative (Path.of_string p) "lib") - | None -> Context.install_ocaml_libdir context + | Some p -> Future.return (Some (Path.of_string p)) + | None -> Context.install_ocaml_libdir context let install_uninstall ~what = let doc = @@ -730,25 +727,32 @@ let install_uninstall ~what = end; (match setup.contexts, prefix_from_command_line, libdir_from_command_line with | _ :: _ :: _, 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 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 (List.map install_files_by_context ~f:(fun (context, install_files) -> - get_prefix context ~from_command_line:prefix_from_command_line >>= fun prefix -> - get_libdir context ~libdir_from_command_line ~prefix_from_command_line >>= fun libdir -> + get_prefix context ~from_command_line:prefix_from_command_line + >>= fun prefix -> + get_libdir context ~libdir_from_command_line + >>= fun libdir -> Future.all_unit (List.map install_files ~f:(fun path -> - let purpose = Future.Build_job install_files in - Future.run ~purpose Strict (Path.to_string opam_installer) - [ sprintf "-%c" what.[0] - ; "--prefix" - ; Path.to_string prefix - ; "--libdir" - ; Path.to_string libdir - ; Path.to_string path - ]))))) + let purpose = Future.Build_job install_files in + Future.run ~purpose Strict (Path.to_string opam_installer) + ([ sprintf "-%c" what.[0] + ; Path.to_string path + ; "--prefix" + ; Path.to_string prefix + ] @ + match libdir with + | None -> [] + | Some p -> [ "--libdir"; Path.to_string p ] + )))))) in ( Term.(const go $ common diff --git a/doc/usage.rst b/doc/usage.rst index 635c1b05..c877e6ba 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -248,29 +248,38 @@ to be able to use ``jbuilder install``. 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: #. if an explicit ``--prefix `` argument is passed, use this path -#. if ``opam`` is present in the ``PATH``, use the output of ``opam config var - prefix`` +#. if ``opam`` is present in the ``PATH`` and is configured, use the + output of ``opam config var prefix`` #. otherwise, take the parent of the directory where ``ocamlc`` was found. -The place where the library files are copied, referred as -**libdir**, is determined as follow for a given build context: +As an exception to this rule, library files might be copied to a +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 +``/lib`` on some systems. -#. if an explicit ``--libdir `` argument is passed, use this path -#. if an explicit ``--prefix `` argument is passed, use ``/lib`` -#. if ``ocamlfind`` is present in the ``PATH``, use the output of - ``ocamlfind printconf destdir`` -#. if ``opam`` is present in the ``PATH``, use the output of ``opam config var - lib`` -#. otherwise, take the directory of the ocaml standard library +Historically, the location where to store OCaml library files was +configured through `findlib +`__ and the +``ocamlfind`` command line tool was used to both install these files +and locate them. Many Linux distributions or other packaging systems +are using this mechanism to setup where OCaml library files should be +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 build context is in -use. +Note that ``--prefix`` and ``--libdir`` are only supported if a single +build context is in use. Workspace configuration ======================= diff --git a/src/context.ml b/src/context.ml index d09e30f7..9b18f32e 100644 --- a/src/context.ml +++ b/src/context.ml @@ -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) in let ocamlc_config_cmd = sprintf "%s -config" (Path.to_string ocamlc) in - Future.run_capture_lines ~env Strict (Path.to_string ocamlc) ["-config"] - >>= fun ocamlc_config -> + 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 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 = List.map ocamlc_config ~f:(fun line -> 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 (c_compiler, ocamlc_cflags, ocamlopt_cflags) 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 { name ; kind @@ -433,17 +434,10 @@ let install_ocaml_libdir t = | Some fn -> (Future.run_capture_line ~env:t.env Strict (Path.to_string fn) ["printconf"; "destdir"] - >>| Path.absolute) + >>| fun s -> + Some (Path.absolute s)) | None -> - (* If there no ocamlfind in the PATH, check if we have opam and assume a standard - 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 - + 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 9f3840bc..cfc906f6 100644 --- a/src/context.mli +++ b/src/context.mli @@ -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 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