diff --git a/bin/import.ml b/bin/import.ml index 61f94edbdd4..db93d03d59f 100644 --- a/bin/import.ml +++ b/bin/import.ml @@ -18,6 +18,7 @@ module Dep = Dune.Dep module Action_to_sh = Dune.Action_to_sh module Dpath = Dune.Dpath module Install = Dune.Install +module Section = Dune.Section module Watermarks = Dune.Watermarks module Promotion = Dune.Promotion module Colors = Dune.Colors diff --git a/bin/install_uninstall.ml b/bin/install_uninstall.ml index 3587f208e24..a129f404628 100644 --- a/bin/install_uninstall.ml +++ b/bin/install_uninstall.ml @@ -264,13 +264,13 @@ end module Sections = struct type t = | All - | Only of Install.Section.Set.t + | Only of Section.Set.t - let sections_conv : Install.Section.t list Cmdliner.Arg.converter = + let sections_conv : Section.t list Cmdliner.Arg.converter = let all = - Install.Section.all |> Install.Section.Set.to_list + Section.all |> Section.Set.to_list |> List.map ~f:(fun section -> - (Install.Section.to_string section, section)) + (Section.to_string section, section)) in Arg.list ~sep:',' (Arg.enum all) @@ -282,12 +282,12 @@ module Sections = struct in match sections with | None -> All - | Some sections -> Only (Install.Section.Set.of_list sections) + | Some sections -> Only (Section.Set.of_list sections) let should_install t section = match t with | All -> true - | Only set -> Install.Section.Set.mem set section + | Only set -> Section.Set.mem set section end let file_operations ~dry_run ~workspace : (module File_operations) = @@ -473,7 +473,7 @@ let install_uninstall ~what = (Path.to_string_maybe_quoted dst); Ops.mkdir_p dir; let executable = - Install.Section.should_set_executable_bit + Section.should_set_executable_bit entry.section in let get_location section package = diff --git a/otherlibs/sites_locations/test/run.t b/otherlibs/sites_locations/test/run.t index 614dc9af6be..334434d669f 100644 --- a/otherlibs/sites_locations/test/run.t +++ b/otherlibs/sites_locations/test/run.t @@ -3,35 +3,65 @@ Test embedding of sites locations information $ mkdir -p a b c - $ for i in a b c; do + $ for i in a b; do + > mkdir -p $i + > cat >$i/dune-project < (lang dune 2.2) + > (name $i) + > (package (name $i) (sites_locations (share data))) + > EOF + > done + + $ for i in c; do > mkdir -p $i > cat >$i/dune-project < (lang dune 2.2) > (name $i) - > (package (name $i) (sites_locations (share data))) + > (package (name $i) (sites_locations (share data) (lib plugins))) > EOF > done - $ for i in a b; do - > cat >$i/dune <a/dune < (library - > (public_name $i) + > (public_name a) > (libraries dune-sites-locations) > ) - > (sites (module sites) (package $i)) + > (sites (module sites) (package a)) > EOF - > cat >$i/$i.ml < let v = "$i" - > let () = Printf.printf "run $i\n%!" - > let () = List.iter (Printf.printf "$i: %s\n%!") Sites.data + + $ cat >a/a.ml < let v = "a" + > let () = Printf.printf "run a\n%!" + > let () = List.iter (Printf.printf "a: %s\n%!") Sites.data + > EOF + + $ cat >b/dune < (library + > (public_name b) + > (libraries c.register dune-sites-locations) + > ) + > (sites (module sites) (package b)) + > (plugin (name c-plugins-b) (libraries b) (site (c plugins))) + > EOF + + $ cat >b/b.ml < let v = "b" + > let () = Printf.printf "run b\n%!" + > let () = C_register.b_registered := true + > let () = List.iter (Printf.printf "b: %s\n%!") Sites.data > EOF - > done $ cat >c/dune < (executable > (public_name c) > (promote (until-clean)) - > (libraries a b dune-sites-locations)) + > (modules c sites) + > (libraries a c.register findlib.dynload dune-sites-locations)) + > (library + > (public_name c.register) + > (name c_register) + > (modules c_register) + > ) > (sites (module sites) (package c)) > (rule > (targets out.log) @@ -39,13 +69,26 @@ Test embedding of sites locations information > (action (with-stdout-to out.log (run %{bin:c})))) > EOF + $ cat >c/c_register.ml < let b_registered = ref false + > EOF + $ cat >c/c.ml < let () = Printf.printf "run c: %s %s\n%!" A.v B.v + > let () = Printf.printf "run c: %s b_registered:%b\n%!" A.v !C_register.b_registered + > let path_sep = if Sys.win32 then ";" else ":" + > let env_ocamlpath = (String.concat path_sep (Sites.plugins@[Sys.getenv "OCAMLPATH"])) + > let () = Findlib.init ~env_ocamlpath () + > let plugins = + > List.concat + > (List.map (fun dir -> (Array.to_list (Sys.readdir dir))) + > ((List.filter Sys.file_exists Sites.plugins))) + > let () = Fl_dynload.load_packages plugins + > let () = Printf.printf "run c: %s b_registered:%b\n%!" A.v !C_register.b_registered > let () = List.iter (Printf.printf "c: %s\n%!") Sites.data > EOF $ cat > dune-project << EOF - > (lang dune 2.0) + > (lang dune 2.2) > EOF $ dune build @@ -55,17 +98,18 @@ Inside _build, we have no sites information: $ _build/default/c/c.exe run a - run b - run c: a b + run c: a b_registered:false + run c: a b_registered:false Once installed, we have the sites information: - $ _install/bin/c + $ OCAMLPATH=_install/lib:$OCAMLPATH _install/bin/c run a a: $TESTCASE_ROOT/_install/share/a/data + run c: a b_registered:false run b b: $TESTCASE_ROOT/_install/share/b/data - run c: a b + run c: a b_registered:true c: $TESTCASE_ROOT/_install/share/c/data Test substitution when promoting @@ -74,10 +118,9 @@ Test substitution when promoting $ c/c.exe run a a: $TESTCASE_ROOT/_build/install/default/share/a/data - run b - b: $TESTCASE_ROOT/_build/install/default/share/b/data - run c: a b - c: $TESTCASE_ROOT/_build/install/default/share/c/data + run c: a b_registered:false + Fatal error: exception Fl_package_base.No_such_package("b", "required by `c-plugins-b'") + [2] Test within dune rules -------------------------------- @@ -86,9 +129,10 @@ Test within dune rules $ cat _build/default/c/out.log run a a: $TESTCASE_ROOT/_build/install/default/share/a/data + run c: a b_registered:false run b b: $TESTCASE_ROOT/_build/install/default/share/b/data - run c: a b + run c: a b_registered:true c: $TESTCASE_ROOT/_build/install/default/share/c/data @@ -97,7 +141,8 @@ Test with dune exec $ dune exec -- c/c.exe run a a: $TESTCASE_ROOT/_build/install/default/share/a/data + run c: a b_registered:false run b b: $TESTCASE_ROOT/_build/install/default/share/b/data - run c: a b + run c: a b_registered:true c: $TESTCASE_ROOT/_build/install/default/share/c/data diff --git a/src/dune/coq_rules.ml b/src/dune/coq_rules.ml index 3f5d4d9c1be..2ae7f683837 100644 --- a/src/dune/coq_rules.ml +++ b/src/dune/coq_rules.ml @@ -221,7 +221,7 @@ let install_rules ~sctx ~dir s = let dst = Path.Local.relative dst_dir vofile_rel in ( None , Install.( - Entry.make Section.Lib_root ~dst:(Path.Local.to_string dst) + Entry.make Lib_root ~dst:(Path.Local.to_string dst) vofile) )) |> List.rev_append (coq_plugins_install_rules ~scope ~package ~dst_dir s) diff --git a/src/dune/dune_file.ml b/src/dune/dune_file.ml index 31bac49f278..5275500a3aa 100644 --- a/src/dune/dune_file.ml +++ b/src/dune/dune_file.ml @@ -1151,16 +1151,33 @@ module Library = struct ~special_builtin_support ~exit_module end +module Plugin = struct + type t = { + package: Package.t; + name: Package.Name.t; + libraries: (Loc.t * Lib_name.t) list; + site: (Loc.t * (Package.Name.t * Package.Name.t)); + } + + let decode = + fields + (let+ name = field "name" Package.Name.decode + and+ libraries = field "libraries" (repeat (located Lib_name.decode)) + and+ site = field "site" (located (pair Package.Name.decode Package.Name.decode)) + and+ package = Pkg.field "package" in + { name; libraries; site; package }) +end + module Install_conf = struct type 'file t = - { section : Install.Section.t + { section : Install.SectionWithSite.t ; files : 'file list ; package : Package.t } let decode = fields - (let+ section = field "section" Install.Section.decode + (let+ section = field "section" Install.SectionWithSite.decode and+ files = field "files" File_binding.Unexpanded.L.decode and+ package = Pkg.field "install" in { section; files; package }) @@ -1348,7 +1365,7 @@ module Executables = struct ~dst:(locp, pub))) |> List.filter_opt in - { Install_conf.section = Bin; files; package }) + { Install_conf.section = Section Bin; files; package }) end module Link_mode = struct @@ -2189,6 +2206,7 @@ type Stanza.t += | External_variant of External_variant.t | Deprecated_library_name of Deprecated_library_name.t | Sites_locations of Sites_locations.t + | Plugin of Plugin.t module Stanzas = struct type t = Stanza.t list @@ -2289,6 +2307,10 @@ module Stanzas = struct , let+ () = Dune_lang.Syntax.since Stanza.syntax (2, 2) and+ t = Sites_locations.decode in [ Sites_locations t ] ) + ; ( "plugin" + , let+ () = Dune_lang.Syntax.since Stanza.syntax (2, 2) + and+ t = Plugin.decode in + [ Plugin t ] ) ] let () = Dune_project.Lang.register Stanza.syntax stanzas @@ -2374,6 +2396,7 @@ let stanza_package = function | Alias { package = Some package; _ } | Rule { package = Some package; _ } | Install { package; _ } + | Plugin { package; _ } | Executables { install_conf = Some { package; _ }; _ } | Documentation { package; _ } | Tests { package = Some package; _ } -> diff --git a/src/dune/dune_file.mli b/src/dune/dune_file.mli index b716bc05554..a125399dcfa 100644 --- a/src/dune/dune_file.mli +++ b/src/dune/dune_file.mli @@ -243,9 +243,18 @@ module Library : sig -> Lib_info.local end +module Plugin : sig + type t = { + package: Package.t; + name: Package.Name.t; + libraries: (Loc.t * Lib_name.t) list; + site: (Loc.t * (Package.Name.t * Package.Name.t)); + } +end + module Install_conf : sig type 'file t = - { section : Install.Section.t + { section : Install.SectionWithSite.t ; files : 'file list ; package : Package.t } @@ -472,6 +481,7 @@ type Stanza.t += | External_variant of External_variant.t | Deprecated_library_name of Deprecated_library_name.t | Sites_locations of Sites_locations.t + | Plugin of Plugin.t val stanza_package : Stanza.t -> Package.t option diff --git a/src/dune/dune_package.ml b/src/dune/dune_package.ml index 4ea68c2aefa..1286f74b6d3 100644 --- a/src/dune/dune_package.ml +++ b/src/dune/dune_package.ml @@ -277,6 +277,7 @@ type t = ; entries : Entry.t list ; version : string option ; sites : Path.t Section.Map.t + ; sites2 : Section.t Package.Name.Map.t ; dir : Path.t } @@ -285,6 +286,7 @@ let decode ~lang ~dir = let+ name = field "name" Package.Name.decode and+ version = field_o "version" string and+ (loc,sites) = located (field ~default:[] "sites" (repeat (pair Section.decode Dpath.decode))) + and+ (loc2,sites2) = located (field ~default:[] "sites2" (repeat (pair Package.Name.decode Section.decode))) and+ entries = leftover_fields_as_sums (Entry.cstrs ~lang ~dir) in let entries = List.map entries ~f:(fun e -> @@ -303,6 +305,14 @@ let decode ~lang ~dir = [ Pp.textf "The section %s appears multiple times" (Section.to_string s)] ) + ; sites2= Package.Name.Map.of_list sites2 + |> (function + | Ok x -> x + | Error (s, _, _) -> + User_error.raise ~loc:loc2 + [ Pp.textf "The section %s appears multiple times" + (Package.Name.to_string s)] + ) } let () = Vfile.Lang.register Stanza.syntax () @@ -318,13 +328,15 @@ let prepend_version ~dune_version sexps = ] @ sexps -let encode ~dune_version { entries; name; version; dir; sites } = +let encode ~dune_version { entries; name; version; dir; sites; sites2 } = let open Dune_lang.Encoder in let sites = (Section.Map.to_list (Section.Map.map ~f:Path.to_absolute_filename sites)) in + let sites2 = (Package.Name.Map.to_list sites2) in let sexp = record_fields [ field "name" Package.Name.encode name; field_o "version" string version; - field_l "sites" (pair Section.encode string) sites + field_l "sites" (pair Section.encode string) sites; + field_l "sites2" (pair Package.Name.encode Section.encode) sites2; ] in let list s = Dune_lang.List s in let entries = @@ -338,7 +350,7 @@ let encode ~dune_version { entries; name; version; dir; sites } = in prepend_version ~dune_version (List.concat [ sexp; entries ]) -let to_dyn { entries; name; version; dir; sites } = +let to_dyn { entries; name; version; dir; sites; sites2 } = let open Dyn.Encoder in record [ ("entries", list Entry.to_dyn entries) @@ -346,6 +358,7 @@ let to_dyn { entries; name; version; dir; sites } = ; ("version", option string version) ; ("dir", Path.to_dyn dir) ; ("sites", Section.Map.to_dyn Path.to_dyn sites) + ; ("sites2", Package.Name.Map.to_dyn Section.to_dyn sites2) ] module Or_meta = struct diff --git a/src/dune/dune_package.mli b/src/dune/dune_package.mli index 4517939c7b4..465177fa7a7 100644 --- a/src/dune/dune_package.mli +++ b/src/dune/dune_package.mli @@ -53,6 +53,7 @@ type t = ; entries : Entry.t list ; version : string option ; sites : Path.t Section.Map.t + ; sites2 : Section.t Package.Name.Map.t ; dir : Path.t } diff --git a/src/dune/findlib/findlib.ml b/src/dune/findlib/findlib.ml index 7ad8f6a3189..8b0296afd0f 100644 --- a/src/dune/findlib/findlib.ml +++ b/src/dune/findlib/findlib.ml @@ -510,6 +510,7 @@ module Root_package = struct ; version = None ; dir = Path.root ; sites = Section.Map.empty + ; sites2 = Opam_package.Name.Map.empty } end diff --git a/src/dune/gen_meta.mli b/src/dune/gen_meta.mli index f953801a095..b1d90c8e283 100644 --- a/src/dune/gen_meta.mli +++ b/src/dune/gen_meta.mli @@ -8,3 +8,4 @@ val gen : -> ?add_directory_entry:bool -> Super_context.Lib_entry.t list -> Meta.t +(** Generate the meta for a package containing some libraries *) diff --git a/src/dune/gen_rules.ml b/src/dune/gen_rules.ml index 2cea41b2cda..62e734befb3 100644 --- a/src/dune/gen_rules.ml +++ b/src/dune/gen_rules.ml @@ -121,6 +121,9 @@ end = struct | Install i -> files_to_install i; empty_none + | Plugin p -> + Plugin_rules.setup_rules ~sctx ~dir p; + empty_none | Cinaps.T cinaps -> Cinaps.gen_rules sctx cinaps ~dir ~scope; empty_none diff --git a/src/dune/install.ml b/src/dune/install.ml index fac36eb0843..d7a9a101db7 100644 --- a/src/dune/install.ml +++ b/src/dune/install.ml @@ -8,6 +8,8 @@ module Dst : sig val to_string : t -> string + val add_prefix: string -> t -> t + val to_install_file : t -> src_basename:string -> section:Section.t -> string option @@ -24,6 +26,8 @@ end = struct let to_string t = t + let add_prefix p t = Filename.concat p t + let explicit t = t let compare = Poly.compare @@ -67,43 +71,22 @@ end module Section = struct include Section - include Comparable.Make (Section) - - let all = - Set.of_list - [ Lib - ; Lib_root - ; Libexec - ; Libexec_root - ; Bin - ; Sbin - ; Toplevel - ; Share - ; Share_root - ; Etc - ; Doc - ; Stublibs - ; Man - ; Misc - ] - - let should_set_executable_bit = function + type t = Section.t = | Lib | Lib_root + | Libexec + | Libexec_root + | Bin + | Sbin | Toplevel | Share | Share_root | Etc | Doc + | Stublibs | Man - | Misc -> - false - | Libexec - | Libexec_root - | Bin - | Sbin - | Stublibs -> - true + | Misc + module Paths = struct type t = @@ -169,13 +152,55 @@ module Section = struct let paths = make ~package:package_name ~destdir:install_dir () in - get paths section + (get paths section) let install_path t section p = Path.relative (get t section) (Dst.to_string p) end end +module SectionWithSite = struct + type t = + | Section of Section.t + | Site of { pkg: Package.Name.t; site: Package.Name.t } + + (* let compare : t -> t -> Ordering.t = Poly.compare *) + + let to_dyn x = + let open Dyn.Encoder in + match x with + | Section s -> constr "Section" [ Section.to_dyn s ] + | Site { pkg; site } -> constr "Section" [ Package.Name.to_dyn pkg; + Package.Name.to_dyn site ] + + let to_string = function + | Section s -> Section.to_string s + | Site {pkg;site} -> sprintf "(site %s %s)" + (Package.Name.to_string pkg) (Package.Name.to_string site) + + + let decode = + let open Dune_lang.Decoder in + sum + [ ("lib", return (Section Lib)) + ; ("lib_root", return (Section Lib_root)) + ; ("libexec", return (Section Libexec)) + ; ("libexec_root", return (Section Libexec_root)) + ; ("bin", return (Section Bin)) + ; ("sbin", return (Section Sbin)) + ; ("toplevel", return (Section Toplevel)) + ; ("share", return (Section Share)) + ; ("share_root", return (Section Share_root)) + ; ("etc", return (Section Etc)) + ; ("doc", return (Section Doc)) + ; ("stublibs", return (Section Stublibs)) + ; ("man", return (Section Man)) + ; ("misc", return (Section Misc)) + ; ("site", pair Package.Name.decode Package.Name.decode + >>| (fun (pkg,site) -> Site {pkg;site})) + ] +end + module Entry = struct type 'src t = { src : 'src @@ -247,6 +272,33 @@ module Entry = struct in { src; dst; section } + let make_with_site section ?dst get_section src = + match section with + | SectionWithSite.Section section -> + make section ?dst src + | Site {pkg;site} -> + let section = get_section ~pkg ~site in + let dst = + adjust_dst ~src:(Expanded (Path.to_string (Path.build src))) ~dst ~section + in + let dst = Dst.add_prefix (Package.Name.to_string site) dst in + let dst_with_pkg_prefix = Dst.add_prefix (Package.Name.to_string pkg) dst in + let (section:Section.t),dst = match section with + | Lib -> Lib_root, dst_with_pkg_prefix + | Libexec -> Libexec_root, dst_with_pkg_prefix + | Share -> Share_root, dst_with_pkg_prefix + | Etc | Doc -> User_error.raise [ Pp.textf "Can't have site in etc and doc for opam" ] + | Lib_root + | Libexec_root | Bin | Sbin + | Toplevel | Share_root + | Stublibs | Man + | Misc -> section, dst + in + { src + ; dst + ; section + } + let set_src t src = { t with src } let relative_installed_path t ~paths = @@ -271,6 +323,15 @@ module Entry = struct } end +module EntryWithSite = struct + type 'src t = + { src : 'src + ; dst : Dst.t + ; section : SectionWithSite.t + } + +end + let files entries = List.fold_left entries ~init:Path.Set.empty ~f:(fun acc (entry : Path.Build.t Entry.t) -> @@ -288,15 +349,16 @@ let gen_install_file entries = pr "%s: [" (Section.to_string section); List.sort ~compare:Entry.compare entries |> List.iter ~f:(fun (e : Path.Build.t Entry.t) -> - let src = Path.to_string (Path.build e.src) in - match - Dst.to_install_file - ~src_basename:(Path.Build.basename e.src) - ~section:e.section e.dst - with - | None -> pr " %S" src - | Some dst -> pr " %S {%S}" src dst); - pr "]"); + let src = Path.to_string (Path.build e.src) in + match + Dst.to_install_file + ~src_basename:(Path.Build.basename e.src) + ~section:e.section e.dst + with + | None -> pr " %S" src + | Some dst -> pr " %S {%S}" src dst); + pr "]" + ); Buffer.contents buf let pos_of_opam_value : OpamParserTypes.value -> OpamParserTypes.pos = function diff --git a/src/dune/install.mli b/src/dune/install.mli index ebcdd3b0d94..72cac493481 100644 --- a/src/dune/install.mli +++ b/src/dune/install.mli @@ -27,8 +27,6 @@ module Section : sig module Set : Set.S with type elt = t - val all : Set.t - val to_string : t -> string val parse_string : string -> (t, string) Result.t @@ -37,10 +35,6 @@ module Section : sig val to_dyn : t -> Dyn.t - (** [true] iff the executable bit should be set for files installed in this - location. *) - val should_set_executable_bit : t -> bool - module Paths : sig type section = t @@ -62,6 +56,22 @@ module Section : sig with type section := t end +module SectionWithSite : sig + + type t = + | Section of Section.t + | Site of { pkg: Package.Name.t; site: Package.Name.t } + + val to_string : t -> string + + (* val parse_string : string -> (t, string) Result.t *) + + val decode : t Dune_lang.Decoder.t + + val to_dyn : t -> Dyn.t + +end + module Entry : sig type 'src t = private { src : 'src @@ -75,7 +85,12 @@ module Entry : sig -> section:Section.t -> Dst.t - val make : Section.t -> ?dst:string -> Path.Build.t -> Path.Build.t t + val make : Section.t -> ?dst:string + -> Path.Build.t -> Path.Build.t t + + val make_with_site : SectionWithSite.t -> ?dst:string + -> (pkg:Package.Name.t -> site:Package.Name.t -> Section.t) + -> Path.Build.t -> Path.Build.t t val set_src : _ t -> 'src -> 'src t @@ -85,6 +100,16 @@ module Entry : sig Path.Build.t t -> paths:Section.Paths.t -> prefix:Path.t -> Path.Build.t t end + +module EntryWithSite : sig + type 'src t = + { src : 'src + ; dst : Dst.t + ; section : SectionWithSite.t + } +end + + val files : Path.Build.t Entry.t list -> Path.Set.t val gen_install_file : Path.Build.t Entry.t list -> string diff --git a/src/dune/install_rules.ml b/src/dune/install_rules.ml index 582aea515f9..e461dcad66c 100644 --- a/src/dune/install_rules.ml +++ b/src/dune/install_rules.ml @@ -143,7 +143,7 @@ end = struct | Dune_file.Library lib -> Lib.DB.available (Scope.libs scope) (Dune_file.Library.best_name lib) | Dune_file.Documentation _ - | Dune_file.Install _ -> + | Dune_file.Install _ | Dune_file.Plugin _ -> true | Dune_file.Executables ({ install_conf = Some _; _ } as exes) -> let compile_info = @@ -247,7 +247,8 @@ end = struct let loc = File_binding.Expanded.src_loc fb in let src = File_binding.Expanded.src fb in let dst = File_binding.Expanded.dst fb in - (Some loc, Install.Entry.make section src ?dst)) + (Some loc, Install.Entry.make_with_site section + (Super_context.get_site_of_packages sctx) src ?dst)) | Dune_file.Library lib -> let sub_dir = (Option.value_exn lib.public).sub_dir in let dir_contents = Dir_contents.get sctx ~dir in @@ -262,6 +263,8 @@ end = struct , Install.Entry.make ~dst:(sprintf "odoc-pages/%s" (Path.Build.basename mld)) Install.Section.Doc mld )) + | Dune_file.Plugin t -> + Plugin_rules.install_rules ~sctx ~dir t | _ -> [] in Package.Name.Map.Multi.add_all acc package.name new_entries) @@ -372,6 +375,7 @@ let gen_dune_package sctx pkg = ; entries ; dir = Path.build pkg_root ; sites + ; sites2 = pkg.sites_locations } in dune_package @@ -411,6 +415,7 @@ let gen_dune_package sctx pkg = Path.build (Config.local_install_lib_dir ~context:ctx.name ~package:name) ; sites = Section.Map.empty + ; sites2 = Package.Name.Map.empty } in Build.write_file diff --git a/src/dune/lib.mli b/src/dune/lib.mli index 68c74062888..8ab6c24cf3a 100644 --- a/src/dune/lib.mli +++ b/src/dune/lib.mli @@ -287,6 +287,7 @@ val to_dune_lib : -> dir:Path.t -> Dune_package.Lib.t Or_exn.t +(** Local libraries *) module Local : sig type lib diff --git a/src/dune/plugin_rules.ml b/src/dune/plugin_rules.ml new file mode 100644 index 00000000000..c038bf9ebbb --- /dev/null +++ b/src/dune/plugin_rules.ml @@ -0,0 +1,43 @@ +open! Stdune +open Dune_file.Plugin + +let meta_file ~dir {name; libraries=_; site=(_,(pkg,site)); _} = + let dir = Path.Build.relative dir ".site" in + let dir = Path.Build.relative dir (Package.Name.to_string pkg) in + let dir = Path.Build.relative dir (Package.Name.to_string site) in + let dir = Path.Build.relative dir (Package.Name.to_string name) in + let meta_file = Path.Build.relative dir "META" in + meta_file + +let setup_rules ~sctx ~dir t = + let meta = meta_file ~dir t in + Build.delayed + (fun () -> + let libs = + Result.List.map + t.libraries + ~f:(Lib.DB.resolve (Super_context.public_libs sctx)) in + let requires = + match libs with + | Ok l -> List.map l ~f:(fun lib -> Lib_name.to_string (Lib.name lib)) + | Error e -> raise e + in + let meta = { + Meta.name = None; + entries = [ + Rule { Meta.var = "requires"; action = Set; predicates = []; + value = String.concat ~sep:" " requires + } ] + } in + Format.asprintf "@[%a@,@]" Meta.pp meta.entries) + |> Build.write_file_dyn meta + |> Super_context.add_rule sctx ~dir + + +let install_rules ~sctx ~dir ({name; site=(loc,(pkg,site));_} as t) = + let meta = meta_file ~dir t in + [Some loc,Install.Entry.make_with_site + ~dst:(sprintf "%s/%s" (Package.Name.to_string name) "META") + (Site {pkg;site}) + ((Super_context.get_site_of_packages sctx)) + meta] diff --git a/src/dune/plugin_rules.mli b/src/dune/plugin_rules.mli new file mode 100644 index 00000000000..739708c5780 --- /dev/null +++ b/src/dune/plugin_rules.mli @@ -0,0 +1,14 @@ +open! Stdune +open Import + +val setup_rules : + sctx:Super_context.t + -> dir:Path.Build.t + -> Dune_file.Plugin.t + -> unit + +val install_rules : + sctx:Super_context.t + -> dir:Path.Build.t + -> Dune_file.Plugin.t + -> (Loc.t option * Path.Build.t Install.Entry.t) list diff --git a/src/dune/section.ml b/src/dune/section.ml index 4c143054cd5..d1c2892a23e 100644 --- a/src/dune/section.ml +++ b/src/dune/section.ml @@ -104,3 +104,39 @@ let decode = let encode v = let open Dune_lang.Encoder in string (to_string v) + +let all = + Set.of_list + [ Lib + ; Lib_root + ; Libexec + ; Libexec_root + ; Bin + ; Sbin + ; Toplevel + ; Share + ; Share_root + ; Etc + ; Doc + ; Stublibs + ; Man + ; Misc + ] + +let should_set_executable_bit = function + | Lib + | Lib_root + | Toplevel + | Share + | Share_root + | Etc + | Doc + | Man + | Misc -> + false + | Libexec + | Libexec_root + | Bin + | Sbin + | Stublibs -> + true diff --git a/src/dune/section.mli b/src/dune/section.mli index a21c1956996..cbf9e97e8ca 100644 --- a/src/dune/section.mli +++ b/src/dune/section.mli @@ -20,6 +20,8 @@ val compare: t -> t -> Ordering.t include Comparable_intf.S with type Key.t = t +val all : Set.t + val to_string : t -> string val of_string : string -> t option @@ -29,3 +31,7 @@ val decode : t Dune_lang.Decoder.t val encode : t Dune_lang.Encoder.t val to_dyn : t -> Dyn.t + +(** [true] iff the executable bit should be set for files installed in this + location. *) +val should_set_executable_bit : t -> bool diff --git a/src/dune/super_context.ml b/src/dune/super_context.ml index 502f9b7de22..e4323e018b4 100644 --- a/src/dune/super_context.ml +++ b/src/dune/super_context.ml @@ -81,6 +81,43 @@ let to_dyn t = Context.to_dyn t.context let host t = Option.value t.host ~default:t +let get_site_of_packages t ~pkg ~site = + match Package.Name.Map.find t.packages pkg with + | Some p -> begin + match Package.Name.Map.find p.sites_locations site with + | Some section -> section + | None -> User_error.raise + [ Pp.textf "Package %s doesn't define a site %s" + (Package.Name.to_string pkg) + (Package.Name.to_string site) + ] + end + | None -> + match Findlib.find_root_package t.context.findlib + ~root_name:(Lib_name.of_string_exn ~loc:None (Package.Name.to_string pkg)) with + | Ok (Dune p) -> begin + match Package.Name.Map.find p.sites2 site with + | Some section -> section + | None -> User_error.raise + [ Pp.textf "Package %s doesn't define a site %s" + (Package.Name.to_string pkg) + (Package.Name.to_string site) + ] + end + | Ok (Findlib _) -> + User_error.raise + [ Pp.textf "The package %s can't define a site %s because it is not a dune package" + (Package.Name.to_string pkg) + (Package.Name.to_string site) + ] + | Error Not_found -> + User_error.raise + [ Pp.textf "The package %s is not found" + (Package.Name.to_string pkg) + ] + | Error (Invalid_dune_package exn) -> + Exn.raise exn + let lib_entries_of_package t pkg_name = Package.Name.Map.find t.lib_entries_by_package pkg_name |> Option.value ~default:[] @@ -396,10 +433,10 @@ let get_installed_binaries stanzas ~(context : Context.t) = acc) in match (stanza : Stanza.t) with - | Dune_file.Install { section = Bin; files; _ } -> + | Dune_file.Install { section = Section Bin; files; _ } -> binaries_from_install files | Dune_file.Executables - ({ install_conf = Some { section = Bin; files; _ }; _ } as exes) -> + ({ install_conf = Some { section = Section Bin; files; _ }; _ } as exes) -> let compile_info = let dune_version = Scope.project d.scope |> Dune_project.dune_version diff --git a/src/dune/super_context.mli b/src/dune/super_context.mli index 9404ab04655..ce44fd0b53f 100644 --- a/src/dune/super_context.mli +++ b/src/dune/super_context.mli @@ -41,6 +41,8 @@ val host : t -> t val external_lib_deps_mode : t -> bool +val get_site_of_packages: t -> pkg:Package.Name.t -> site:Package.Name.t -> Section.t + module Lib_entry : sig type t = | Library of Lib.Local.t