diff --git a/doc/manual.org b/doc/manual.org index fbf1305d..fcab364f 100644 --- a/doc/manual.org +++ b/doc/manual.org @@ -513,44 +513,6 @@ The typical use of the =alias= stanza is to define tests: See the [[runtest][section about running tests]] for details. -**** provides - -The =provides= stanza allows you to globally name a file, either a -source file or a target. This is especially important for build tools; -by using the =provides= mechanism, you don't need to know whether the -binary is in the workspace or installed. - -The syntax is as follow: - -#+begin_src scheme -(provides ( (file ))) -#+end_src - -== is the name under which the artifact can be referred and -== is the file it resolves to. When == can be -guessed from the ==, you can use the following shorter syntax: - -#+begin_src scheme -(provides ) -#+end_src - -In this case, the file name is guessed as follow: - -- if == contains a =:=, the file name is anything that comes - after the first =:= -- otherwise it is the same as == - -Once you have written a =provides= stanza, you can refer to the file -in points to using the special forms =${bin:}= or -=${findlib::}= inside =(action ...)= fields. See the -[[Variables expansion][section about variables expansion]] for details. - -Note that any file referred by a =provides= stanza should probably be -installed as well, using an [[install]] stanza. If the file is meant to be -installed in a library directory, then its name should be of the form -=:=. If it is meant to be installed in the -=bin= directory, then its name should be the program name. - **** install The =install= stanza is what lets you describe what Jbuilder should @@ -650,20 +612,24 @@ In addition, =(action ...)= fields support the following special variables: - =@= expands to the list of target, separated by spaces - =<= expands to the first dependency, or the empty string if there are no dependencies - =^= expands to the list of dependencies, separated by spaces -- =exe:= expands to ==, except when cross-compiling, in +- =path:= expands to == +- =exe:= is the same as ==, except when cross-compiling, in which case it will expand to == from the host build context - =bin:= expands to a path to =program=. If =program= is - provided by a jbuild in the workspace (see [[provides][provides stanzas]]), the + installed by a package in the workspace (see [[install][install stanzas]]), the locally built binary will be used, otherwise it will be searched in the =PATH= of the current build context -- =findlib::= expands to a path to file +- =lib::= expands to a path to file == of library ==. If == is available in the current workspace, the local file will be used, otherwise the one from the installed world will be used +- =libexec::= is the same as =lib:...= + except when cross-compiling, in which case it will expand to the + file from the host build context -The last two forms of variable are what allows you to write custom -rules that work transparently whether things are installed or not. +The =${:...}= forms are what allows you to write custom rules +that work transparently whether things are installed or not. ***** Alternative dependencies @@ -832,9 +798,8 @@ of these two forms: In both case, all atoms in the argument of this field supports [[Variables expansion][variables expansion]]. Moreover, you don't need to specify dependencies -explicitly for the special =${exe:...}=, =${bin:...}= or -=${findlib:...}= forms, these are recognized automatically by -Jbuilder. +explicitly for the special =${:...}= forms, these are recognized +automatically handled by Jbuilder. The DSL is preferable in general as it will make your package more portable. It is currently quite limited, so the recommendation is to diff --git a/src/artifacts.ml b/src/artifacts.ml new file mode 100644 index 00000000..6e7a015c --- /dev/null +++ b/src/artifacts.ml @@ -0,0 +1,83 @@ +open Import +open Jbuild_types + +type t = + { context : Context.t + ; provides : Path.t String_map.t + ; local_bins : String_set.t + ; local_libs : String_set.t + } + +let create context stanzas = + let local_bins, local_libs, provides = + List.fold_left stanzas ~init:(String_set.empty, String_set.empty, String_map.empty) + ~f:(fun acc (dir, stanzas) -> + List.fold_left stanzas ~init:acc + ~f:(fun (local_bins, local_libs, provides) stanza -> + match (stanza : Stanza.t) with + | Provides { name; file } -> + (local_bins, + local_libs, + String_map.add provides ~key:name ~data:(Path.relative dir file)) + | Install { section = Bin; files; _ } -> + (List.fold_left files ~init:local_bins ~f:(fun acc { Install_conf. src; dst } -> + let name = + match dst with + | Some s -> s + | None -> Filename.basename src + in + String_set.add name acc), + local_libs, + provides) + | Library { public_name = Some name; _ } -> + (local_bins, + String_set.add name local_libs, + provides) + | _ -> + (local_bins, local_libs, provides))) + in + { context + ; provides + ; local_bins + ; local_libs + } + +let binary t name = + if String_set.mem name t.local_bins then + Ok (Path.relative (Config.local_install_dir ~context:t.context.name) name) + else + match String_map.find name t.provides with + | Some p -> Ok p + | None -> + match Context.which t.context name with + | Some p -> Ok p + | None -> + Error + { fail = fun () -> + die "Program %s not found in the tree or in the PATH" name + } + +let file_of_lib ?(use_provides=false) t ~lib ~file = + if String_set.mem lib t.local_libs then + let lib_install_dir = + Path.relative (Config.local_install_dir ~context:t.context.name) + (Findlib.root_package_name lib) + in + Ok (Path.relative lib_install_dir file) + else + match Findlib.find t.context.findlib lib with + | Some pkg -> + Ok (Path.relative pkg.dir file) + | None -> + match + if use_provides then + String_map.find (sprintf "%s:%s" lib file) t.provides + else + None + with + | Some p -> Ok p + | None -> + Error + { fail = fun () -> + die "Library %s not found in the tree or in the PATH" lib + } diff --git a/src/artifacts.mli b/src/artifacts.mli new file mode 100644 index 00000000..67fc07ca --- /dev/null +++ b/src/artifacts.mli @@ -0,0 +1,21 @@ +(** [Named_artifact] provides a way to reference artifacts in jbuild rules without having + to hardcode their exact locations. These named artifacts will be looked up + appropriately (in the tree, or for the public release, possibly in the PATH or in + findlib). *) + +open! Import + +type t + +val create : Context.t -> (Path.t * Jbuild_types.Stanza.t list) list -> t + +(** A named artifact that is looked up in the PATH if not found in the tree *) +val binary : t -> string -> (Path.t, fail) result + +(** A named artifact that is looked up in the given library. *) +val file_of_lib + : ?use_provides:bool + -> t + -> lib:string + -> file:string + -> (Path.t, fail) result diff --git a/src/build.ml b/src/build.ml index feab1dba..4542699a 100644 --- a/src/build.ml +++ b/src/build.ml @@ -270,8 +270,8 @@ module Shexp = struct exec t ~dir ~env ~env_extra:String_map.empty ~stdout_to:None ~tail:true ~f end -let action action ~dir ~env ~targets = - prim ~targets (fun f -> +let action action ~dir ~env ~targets ~expand:f = + prim ~targets (fun () -> match (action : _ Action.t) with | Bash cmd -> Future.run Strict ~dir:(Path.to_string dir) ~env @@ -288,6 +288,14 @@ let copy ~src ~dst = create_file ~target:dst (fun () -> copy_file ~src:(Path.to_string src) ~dst:(Path.to_string dst)) +let symlink ~src ~dst = + if Sys.win32 then + copy ~src ~dst + else + path src >>> + create_file ~target:dst (fun () -> + Unix.symlink (Path.to_string src) (Path.to_string dst)) + let touch target = create_file ~target (fun _ -> Unix.close diff --git a/src/build.mli b/src/build.mli index ff7774b4..ebde3cc3 100644 --- a/src/build.mli +++ b/src/build.mli @@ -83,13 +83,16 @@ val action -> dir:Path.t -> env:string array -> targets:Path.t list - -> (dir:Path.t -> 'a -> string, unit) t + -> expand:(dir:Path.t -> 'a -> string) + -> (unit, unit) t (** Create a file with the given contents. *) val echo : Path.t -> (string, unit) t val copy : src:Path.t -> dst:Path.t -> (unit, unit) t +val symlink : src:Path.t -> dst:Path.t -> (unit, unit) t + val touch : Path.t -> (unit, unit) t type lib_dep_kind = diff --git a/src/config.ml b/src/config.ml new file mode 100644 index 00000000..7e01ed50 --- /dev/null +++ b/src/config.ml @@ -0,0 +1,5 @@ +open! Import + +let local_install_dir = + let dir = Path.(relative root) "install" in + fun ~context -> Path.relative dir context diff --git a/src/config.mli b/src/config.mli new file mode 100644 index 00000000..073ef3d6 --- /dev/null +++ b/src/config.mli @@ -0,0 +1,6 @@ +(** Configuration parameters *) + +open! Import + +(** Local installation directory *) +val local_install_dir : context:string -> Path.t diff --git a/src/context.ml b/src/context.ml index d4a0c880..6cd0c2d9 100644 --- a/src/context.ml +++ b/src/context.ml @@ -63,6 +63,7 @@ type t = ; ast_intf_magic_number : string ; cmxs_magic_number : string ; cmt_magic_number : string + ; which_cache : (string, Path.t option) Hashtbl.t } let compare a b = compare a.name b.name @@ -102,6 +103,9 @@ let get_env env var = in loop 0 +let which ~cache ~path x = + Hashtbl.find_or_add cache x ~f:(Bin.which ~path) + let create ~(kind : Kind.t) ~path ~env ~name ~merlin = let opam_var_cache = Hashtbl.create 128 in (match kind with @@ -111,7 +115,8 @@ let create ~(kind : Kind.t) ~path ~env ~name ~merlin = let prog_not_found_in_path prog = die "Program %s not found in PATH (context: %s)" prog name in - let which x = Bin.which ~path x in + let which_cache = Hashtbl.create 128 in + let which x = which ~cache:which_cache ~path x in let ocamlc = match which "ocamlc" with | None -> prog_not_found_in_path "ocamlc" @@ -248,6 +253,8 @@ let create ~(kind : Kind.t) ~path ~env ~name ~merlin = ; ast_intf_magic_number = get "ast_intf_magic_number" ; cmxs_magic_number = get "cmxs_magic_number" ; cmt_magic_number = get "cmt_magic_number" + + ; which_cache } let opam_config_var t var = opam_config_var ~env:t.env ~cache:t.opam_var_cache var @@ -310,7 +317,7 @@ let create_for_opam ?root ~switch ~name ?(merlin=false) () = create ~kind:(Opam { root; switch }) ~path ~env:(extend_env ~vars ~env) ~name ~merlin -let which t s = Bin.which ~path:t.path s +let which t s = which ~cache:t.which_cache ~path:t.path s let install_prefix t = opam_config_var t "prefix" >>| function diff --git a/src/context.mli b/src/context.mli index 06c10bca..6fa53c7c 100644 --- a/src/context.mli +++ b/src/context.mli @@ -103,6 +103,8 @@ type t = ; ast_intf_magic_number : string ; cmxs_magic_number : string ; cmt_magic_number : string + + ; which_cache : (string, Path.t option) Hashtbl.t } (** Compare the context names *) diff --git a/src/findlib.ml b/src/findlib.ml index 3f46a7ef..58c8dbe5 100644 --- a/src/findlib.ml +++ b/src/findlib.ml @@ -392,6 +392,11 @@ let find_exn t name = Hashtbl.add t.packages ~key:name ~data:Absent; raise (Package_not_found name) +let find t name = + match find_exn t name with + | exception (Package_not_found _) -> None + | x -> Some x + let available t name = match find_exn t name with | _ -> true diff --git a/src/findlib.mli b/src/findlib.mli index 34e01388..c5f9300f 100644 --- a/src/findlib.mli +++ b/src/findlib.mli @@ -22,6 +22,7 @@ type package = ; has_headers : bool } +val find : t -> string -> package option val find_exn : t -> string -> package val available : t -> string -> bool diff --git a/src/gen_rules.ml b/src/gen_rules.ml index 84f83818..79ba27e8 100644 --- a/src/gen_rules.ml +++ b/src/gen_rules.ml @@ -240,21 +240,21 @@ module Gen(P : Params) = struct let _ = t end - module Named_artifacts = struct - open Named_artifacts + module Artifacts = struct + open Artifacts - let t = create ~path:ctx.path findlib (List.map P.stanzas ~f:(fun d -> (d.ctx_dir, d.stanzas))) + let t = create ctx (List.map P.stanzas ~f:(fun d -> (d.ctx_dir, d.stanzas))) - let binary name = Build.arr (fun _ -> binary t name) - let in_findlib ~dir ~dep_kind name = - let pkg = + let binary name = binary t name + let file_of_lib ?use_provides ~dir name = + let lib, file = match String.lsplit2 name ~on:':' with - | None -> invalid_arg "Named_artifacts.in_findlib" - | Some (pkg, _) -> pkg + | None -> + Loc.fail (Loc.in_file (Path.to_string (Path.relative dir "jbuild"))) + "invalid ${lib:...} form: %s" name + | Some x -> x in - Build.record_lib_deps ~dir ~kind:dep_kind [Direct pkg] - >>> - (Build.arr (fun () -> in_findlib t name)) + (lib, file_of_lib t ~lib ~file ?use_provides) (* Hides [t] so that we don't resolve things statically *) let t = () @@ -1270,53 +1270,78 @@ module Gen(P : Params) = struct +-----------------------------------------------------------------+ *) module Action_interpret : sig - type expander - - val expand + val run : Action.Unexpanded.t -> dir:Path.t -> dep_kind:Build.lib_dep_kind -> targets:Path.t list -> deps:Dep_conf.t list - -> (unit, expander) Build.t - - val run - : Action.Unexpanded.t - -> dir:Path.t - -> targets:Path.t list - -> (expander, unit) Build.t + -> (unit, unit) Build.t end = struct module U = Action.Unexpanded - type expander = dir:Path.t -> String_with_vars.t -> string + type resolved_forms = + { (* Mapping from ${...} forms to their resolutions *) + artifacts : Path.t String_map.t + ; (* Failed resolutions *) + failures : fail list + ; (* All "name" for ${lib:name:...} forms *) + lib_deps : String_set.t + } - type artefact = - | Direct of Path.t - | Dyn of (unit, Path.t) Build.t + let add_artifact ?lib_dep acc ~var result = + let lib_deps = + match lib_dep with + | None -> acc.lib_deps + | Some lib -> String_set.add lib acc.lib_deps + in + match result with + | Ok path -> + { acc with + artifacts = String_map.add acc.artifacts ~key:var ~data:path + ; lib_deps + } + | Error fail -> + { acc with + failures = fail :: acc.failures + ; lib_deps + } - let extract_artifacts ~dir ~dep_kind t = - U.fold t ~init:String_map.empty ~f:(fun acc var -> - let module N = Named_artifacts in + let extract_artifacts ~dir t = + let init = + { artifacts = String_map.empty + ; failures = [] + ; lib_deps = String_set.empty + } + in + U.fold t ~init ~f:(fun acc var -> + let module A = Artifacts in match String.lsplit2 var ~on:':' with - (* CR-someday jdimino: map the exe to the host exe here *) - | Some ("exe", s) -> - String_map.add acc ~key:var ~data:(Direct (Path.relative dir s)) - | Some ("bin", s) -> String_map.add acc ~key:var ~data:(Dyn (N.binary s)) + | Some ("exe" , s) -> add_artifact acc ~var (Ok (Path.relative dir s)) + | Some ("path" , s) -> add_artifact acc ~var (Ok (Path.relative dir s)) + | Some ("bin" , s) -> add_artifact acc ~var (A.binary s) + | Some ("lib" , s) + | Some ("libexec" , s) -> + let lib_dep, res = A.file_of_lib ~dir s in + add_artifact acc ~var ~lib_dep res + (* CR-someday jdimino: allow this only for (jbuild_version jane_street) *) | Some ("findlib" , s) -> - String_map.add acc ~key:var ~data:(Dyn (N.in_findlib ~dir ~dep_kind s)) + let lib_dep, res = A.file_of_lib ~dir s ~use_provides:true in + add_artifact acc ~var ~lib_dep res | _ -> acc) - let expand_string_with_vars ~artifact_map ~targets ~deps : expander = + let expand_string_with_vars ~artifacts ~targets ~deps = let dep_exn ~dir name = function | Some dep -> Path.reach ~from:dir dep | None -> die "cannot use ${%s} with files_recursively_in" name in let lookup ~dir var_name = - match String_map.find var_name artifact_map with + match String_map.find var_name artifacts with | Some path -> Some (Path.reach ~from:dir path) | None -> match var_name with - | "@" -> Some (String.concat ~sep:" " (List.map targets ~f:(Path.reach ~from:dir))) + | "@" -> Some (String.concat ~sep:" " + (List.map targets ~f:(Path.reach ~from:dir))) | "<" -> Some (match deps with [] -> "" | dep1::_ -> dep_exn ~dir var_name dep1) | "^" -> let deps = List.map deps ~f:(dep_exn ~dir var_name) in @@ -1326,42 +1351,26 @@ module Gen(P : Params) = struct fun ~dir str -> String_with_vars.expand str ~f:(lookup ~dir) - let expand t ~dir ~dep_kind ~targets ~deps = + let run t ~dir ~dep_kind ~targets ~deps = let deps = List.map deps ~f:(fun dep -> Option.map (Dep_conf_interpret.only_plain_file ~dir dep) ~f:(Path.relative dir)) in - let needed_artifacts = extract_artifacts ~dir ~dep_kind t in - if String_map.is_empty needed_artifacts then - let expand = expand_string_with_vars ~artifact_map:String_map.empty ~targets ~deps in - Build.return expand - else begin - let directs, dyns = - String_map.bindings needed_artifacts - |> List.partition_map ~f:(function - | (name, Direct x) -> Inl (name, x) - | (name, Dyn x) -> Inr (name, x)) - in - Build.fanout - (Build.paths (List.map directs ~f:snd)) - (Build.all (List.map dyns ~f:(fun (name, artifact) -> - artifact - >>> - Build.arr (fun path -> (name, path))))) - >>^ snd + let forms = extract_artifacts ~dir t in + let build = + Build.record_lib_deps ~dir ~kind:dep_kind + (String_set.elements forms.lib_deps + |> List.map ~f:(fun s -> Lib_dep.Direct s)) >>> - Build.dyn_paths (Build.arr (List.map ~f:snd)) + Build.paths (String_map.values forms.artifacts) >>> - Build.arr (fun artifacts -> - let artifact_map = - String_map.of_alist_exn (List.rev_append directs artifacts) - in - expand_string_with_vars ~artifact_map ~targets ~deps) - end - - let run action ~dir ~targets = - Build.action action ~dir ~env:ctx.env ~targets + Build.action t ~dir ~env:ctx.env ~targets + ~expand:(expand_string_with_vars ~artifacts:forms.artifacts ~targets ~deps) + in + match forms.failures with + | [] -> build + | fail :: _ -> Build.fail fail >>> build end (* +-----------------------------------------------------------------+ @@ -1373,17 +1382,12 @@ module Gen(P : Params) = struct add_rule (Dep_conf_interpret.dep_of_list ~dir rule.deps >>> - Action_interpret.expand + Action_interpret.run rule.action ~dir ~dep_kind:Required ~targets - ~deps:rule.deps - >>> - Action_interpret.run - rule.action - ~dir - ~targets) + ~deps:rule.deps) let alias_rules (alias_conf : Alias_conf.t) ~dir = let digest = @@ -1407,13 +1411,13 @@ module Gen(P : Params) = struct | None -> deps | Some action -> deps - >>> Action_interpret.expand + >>> Action_interpret.run action ~dir ~dep_kind:Required ~targets:[] ~deps:alias_conf.deps - >>> Action_interpret.run action ~dir ~targets:[] in + in add_rule (deps >>> dummy) (* +-----------------------------------------------------------------+ @@ -1708,6 +1712,13 @@ module Gen(P : Params) = struct List.exists [ "README"; "LICENSE"; "CHANGE"; "HISTORY"] ~f:(fun prefix -> String.is_prefix fn ~prefix) + let local_install_rules (entries : Install.Entry.t list) ~package = + let install_dir = Config.local_install_dir ~context:ctx.name in + List.iter entries ~f:(fun entry -> + let dst = Install.Entry.relative_installed_path entry ~package in + add_rule + (Build.symlink ~src:entry.src ~dst:(Path.append install_dir dst))) + let install_file package_path package = let entries = List.concat_map stanzas_to_consider_for_install ~f:(fun (dir, stanza) -> @@ -1749,6 +1760,7 @@ module Gen(P : Params) = struct let fn = Path.relative (Path.append ctx.build_dir package_path) (package ^ ".install") in + local_install_rules entries ~package; add_rule (Build.path_set (Install.files entries) >>> Build.create_file ~target:fn (fun () -> diff --git a/src/import.ml b/src/import.ml index dcd524de..bac55fbd 100644 --- a/src/import.ml +++ b/src/import.ml @@ -97,7 +97,7 @@ module Hashtbl = struct match find t key with | Some x -> x | None -> - let x = f () in + let x = f key in add t ~key ~data:x; x end @@ -227,6 +227,14 @@ module String = struct (sub s ~pos:0 ~len:i, sub s ~pos:(i + 1) ~len:(String.length s - i - 1)) + let rsplit2 s ~on = + match rindex s on with + | exception Not_found -> None + | i -> + Some + (sub s ~pos:0 ~len:i, + sub s ~pos:(i + 1) ~len:(String.length s - i - 1)) + let index s ch = match index s ch with | i -> Some i diff --git a/src/install.ml b/src/install.ml index ee8b437c..727a1ceb 100644 --- a/src/install.ml +++ b/src/install.ml @@ -61,6 +61,51 @@ module Entry = struct ; dst ; section } + + module Paths = struct + let lib = Path.(relative root) "lib" + let libexec = Path.(relative root) "libexec" + let bin = Path.(relative root) "bin" + let sbin = Path.(relative root) "sbin" + let toplevel = Path.(relative root) "lib/toplevel" + let share = Path.(relative root) "share" + let share_root = Path.(relative root) "share_root" + let etc = Path.(relative root) "etc" + let doc = Path.(relative root) "doc" + let stublibs = Path.(relative root) "lib/stublibs" + let man = Path.(relative root) "man" + end + + let relative_installed_path t ~package = + let main_dir = + match t.section with + | Bin -> Paths.bin + | Sbin -> Paths.sbin + | Toplevel -> Paths.toplevel + | Share_root -> Paths.share_root + | Stublibs -> Paths.stublibs + | Man -> Paths.man + | Lib -> Path.relative Paths.lib package + | Libexec -> Path.relative Paths.libexec package + | Share -> Path.relative Paths.share package + | Etc -> Path.relative Paths.etc package + | Doc -> Path.relative Paths.doc package + | Misc -> invalid_arg "Install.Entry.relative_installed_path" + in + let dst = + match t.dst with + | Some x -> x + | None -> + let dst = Path.basename t.src in + match t.section with + | Man -> begin + match String.rsplit2 dst ~on:'.' with + | None -> dst + | Some (_, sec) -> sprintf "man%s/%s" sec dst + end + | _ -> dst + in + Path.relative main_dir dst end module SMap = Map.Make(Section) diff --git a/src/install.mli b/src/install.mli index 9a89569e..aa5272eb 100644 --- a/src/install.mli +++ b/src/install.mli @@ -26,6 +26,8 @@ module Entry : sig } val make : Section.t -> ?dst:string -> Path.t -> t + + val relative_installed_path : t -> package:string -> Path.t end val files : Entry.t list -> Path.Set.t diff --git a/src/jbuild_types.ml b/src/jbuild_types.ml index 34f5c2b5..d608d82c 100644 --- a/src/jbuild_types.ml +++ b/src/jbuild_types.ml @@ -701,7 +701,6 @@ module Stanza = struct ; cstr "rule" (Rule.v1 @> nil) (fun x -> [Rule x]) ; cstr "ocamllex" (list string @> nil) (fun x -> rules (Rule.ocamllex_v1 x)) ; cstr "ocamlyacc" (list string @> nil) (fun x -> rules (Rule.ocamlyacc_v1 x)) - ; cstr "provides" (Provides.v1 @> nil) (fun x -> [Provides x]) ; cstr "install" (Install_conf.v1 @> nil) (fun x -> [Install x]) ; cstr "alias" (Alias_conf.v1 @> nil) (fun x -> [Alias x]) (* Just for validation and error messages *) diff --git a/src/named_artifacts.ml b/src/named_artifacts.ml deleted file mode 100644 index 4156957e..00000000 --- a/src/named_artifacts.ml +++ /dev/null @@ -1,40 +0,0 @@ -open Import -open Jbuild_types - -type t = - { path : Path.t list - ; findlib : Findlib.t - ; artifacts : (string, Path.t) Hashtbl.t - } - -let create ~path findlib stanzas = - let artifacts : (string, Path.t) Hashtbl.t = Hashtbl.create 1024 in - List.iter stanzas ~f:(fun (dir, stanzas) -> - List.iter stanzas ~f:(fun stanza -> - match (stanza : Stanza.t) with - | Provides { name; file } -> - Hashtbl.add artifacts ~key:name ~data:(Path.relative dir file) - | _ -> ())); - { path; findlib; artifacts } - -let binary t name = - match Hashtbl.find t.artifacts name with - | Some p -> p - | None -> - match Bin.which ~path:t.path name with - | Some p -> - Hashtbl.add t.artifacts ~key:name ~data:p; - p - | None -> - die "Program %s not found in the tree or in the PATH" name - -let in_findlib t name = - match Hashtbl.find t.artifacts name with - | Some p -> p - | None -> - match String.lsplit2 name ~on:':' with - | None -> invalid_arg "Named_artifacts.in_findlib" - | Some (pkg, file) -> - let p = Path.relative (Findlib.find_exn t.findlib pkg).dir file in - Hashtbl.add t.artifacts ~key:name ~data:p; - p diff --git a/src/named_artifacts.mli b/src/named_artifacts.mli deleted file mode 100644 index 68b71b56..00000000 --- a/src/named_artifacts.mli +++ /dev/null @@ -1,20 +0,0 @@ -(** [Named_artifact] provides a way to reference artifacts in jbuild rules without having - to hardcode their exact locations. These named artifacts will be looked up - appropriately (in the tree, or for the public release, possibly in the PATH or in - findlib). *) - -open! Import - -type t - -val create : path:Path.t list -> Findlib.t -> (Path.t * Jbuild_types.Stanza.t list) list -> t - -(** In the three following functions, the string argument matches the first argument of - the [(provides ...)] stanza in the jbuild. *) - -(** A named artifact that is looked up in the PATH if not found in the tree *) -val binary : t -> string -> Path.t - -(** A named artifact that is looked up in the given findlib package if not found in the - tree. Syntax is: [":"]. *) -val in_findlib : t -> string -> Path.t diff --git a/src/workspace.ml b/src/workspace.ml index d0f826c1..667b68b5 100644 --- a/src/workspace.ml +++ b/src/workspace.ml @@ -51,6 +51,7 @@ let t sexps = if name = "" || String.is_prefix name ~prefix:"." || name = "log" || + name = "install" || String.contains name '/' || String.contains name '\\' then of_sexp_errorf sexp "%S is not allowed as a build context name" name;