From 747cf220c61d10461603856f4d684d0cfe3aa864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Bobot?= Date: Wed, 5 Jul 2017 15:10:41 +0200 Subject: [PATCH] Install by specifying libdir for opam-installer - change default findlib directory (ocamlc -where) --- bin/main.ml | 22 +++++++++++++---- doc/usage.rst | 20 +++++++++++---- src/context.ml | 66 ++++++++++++++++++++++++++++++------------------- src/context.mli | 1 + 4 files changed, 74 insertions(+), 35 deletions(-) diff --git a/bin/main.ml b/bin/main.ml index eff34be4..5d7161f3 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -685,12 +685,20 @@ 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 = + 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 + let install_uninstall ~what = let doc = sprintf "%s packages using opam-installer." (String.capitalize_ascii what) in let name_ = Arg.info [] ~docv:"PACKAGE" in - let go common prefix pkgs = + let go common prefix_from_command_line libdir_from_command_line pkgs = set_common common ~targets:[]; let opam_installer = opam_installer () in let log = Log.create () in @@ -720,15 +728,16 @@ let install_uninstall ~what = (List.map missing_install_files ~f:(fun p -> sprintf "- %s" (Path.to_string p)))) end; - (match setup.contexts, prefix with - | _ :: _ :: _, Some _ -> - die "Cannot specify --prefix when installing into multiple contexts!" + (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!" | _ -> ()); let module CMap = Map.Make(Context) 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 >>= fun prefix -> + 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 -> Future.all_unit (List.map install_files ~f:(fun path -> let purpose = Future.Build_job install_files in @@ -736,12 +745,15 @@ let install_uninstall ~what = [ sprintf "-%c" what.[0] ; "--prefix" ; Path.to_string prefix + ; "--libdir" + ; Path.to_string libdir ; Path.to_string path ]))))) in ( Term.(const go $ common $ Arg.(value & opt (some dir) None & info ["prefix"]) + $ Arg.(value & opt (some dir) None & info ["libdir"]) $ Arg.(value & pos_all string [] name_)) , Term.info what ~doc ~man:help_secs) diff --git a/doc/usage.rst b/doc/usage.rst index 38c74ce2..d597857a 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -248,17 +248,27 @@ to be able to use ``jbuilder install``. Destination ----------- -The place where the build artifacts are copied, usually referred as +The place where the build artifacts (except ocaml libraries) 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`` -#. otherwise, take the directory where ``ocamlc`` was found, and append - ``../lib`` to it. For instance if ``ocamlc`` is found in ``/usr/bin``, use - ``/usr`` +#. otherwise, take the parent of the directory where ``ocamlc`` was found. -Note that ``--prefix`` is only supported if a single build context is in +The ocaml libraries build artifacts are copied, referred as +**libdir**, is determined as follow for a given build context: + +#. if an explicit ``--libdir `` argument is passed, use this path +#. 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 + + + +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 f3d2c60e..aa5e8692 100644 --- a/src/context.ml +++ b/src/context.ml @@ -198,31 +198,8 @@ 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 - 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 - [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) -> + Future.run_capture_lines ~env Strict (Path.to_string ocamlc) ["-config"] + >>= fun ocamlc_config -> let ocamlc_config = List.map ocamlc_config ~f:(fun line -> match String.index line ':' with @@ -301,6 +278,28 @@ 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 @@ -426,6 +425,23 @@ let install_prefix t = | Some x -> Path.absolute x | 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 -> + (Future.run_capture_line ~env:t.env Strict + (Path.to_string fn) ["printconf"; "destdir"] + >>| Path.absolute) + | 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 + (* 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 0602bbc2..9f3840bc 100644 --- a/src/context.mli +++ b/src/context.mli @@ -144,6 +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 env_for_exec : t -> string array