From a3933a2c1860fc920ad02b0971ea7be2ce14fac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Bobot?= Date: Wed, 19 Jul 2017 16:26:48 +0200 Subject: [PATCH] Add public_interfaces selection for libraries (#106) Add a field "public_interfaces" to library stanza listing which modules are public. Private modules won't be accessible outside the scope where the library is defined. --- doc/jbuild.rst | 4 ++ src/gen_rules.ml | 44 ++++++++++++------- src/install.ml | 2 + src/install.mli | 2 + src/jbuild.ml | 8 ++++ src/jbuild.mli | 6 +++ src/lib.ml | 32 +++++++++----- src/lib.mli | 17 +++++-- src/merlin.ml | 12 ++--- src/merlin.mli | 3 +- src/module_compilation.ml | 12 ++--- src/module_compilation.mli | 2 + src/odoc.ml | 2 +- src/super_context.ml | 10 ++--- src/super_context.mli | 1 + test/jbuild | 12 +++++ .../workspaces/public_interfaces/bad/bad.opam | 0 test/workspaces/public_interfaces/bad/jbuild | 5 +++ test/workspaces/public_interfaces/bad/main.ml | 1 + .../public_interfaces/good/good.opam | 0 test/workspaces/public_interfaces/good/jbuild | 5 +++ .../workspaces/public_interfaces/good/main.ml | 1 + .../workspaces/public_interfaces/mylib/bad.ml | 1 + .../public_interfaces/mylib/good.ml | 1 + .../workspaces/public_interfaces/mylib/jbuild | 13 ++++++ .../public_interfaces/mylib/mylib.opam | 0 .../public_interfaces/mylib/mylib2.opam | 0 .../public_interfaces/mylib/see_private.ml | 1 + 28 files changed, 146 insertions(+), 51 deletions(-) create mode 100644 test/workspaces/public_interfaces/bad/bad.opam create mode 100644 test/workspaces/public_interfaces/bad/jbuild create mode 100644 test/workspaces/public_interfaces/bad/main.ml create mode 100644 test/workspaces/public_interfaces/good/good.opam create mode 100644 test/workspaces/public_interfaces/good/jbuild create mode 100644 test/workspaces/public_interfaces/good/main.ml create mode 100644 test/workspaces/public_interfaces/mylib/bad.ml create mode 100644 test/workspaces/public_interfaces/mylib/good.ml create mode 100644 test/workspaces/public_interfaces/mylib/jbuild create mode 100644 test/workspaces/public_interfaces/mylib/mylib.opam create mode 100644 test/workspaces/public_interfaces/mylib/mylib2.opam create mode 100644 test/workspaces/public_interfaces/mylib/see_private.ml diff --git a/doc/jbuild.rst b/doc/jbuild.rst index c55cff38..3b48d8a7 100644 --- a/doc/jbuild.rst +++ b/doc/jbuild.rst @@ -81,6 +81,10 @@ modules you want. letter. For instance to exclude module ``Foo``: ``(modules (:standard \ foo))`` +- ``(public_interfaces )`` specifies the interfaces `.cmi` of which + modules are installed. ```` uses the same + `Ordered set language` than ````. + - ``(libraries ())`` is used to specify the dependencies of the library. See the section about `Library dependencies`_ for more details diff --git a/src/gen_rules.ml b/src/gen_rules.ml index 46cc34aa..82b66f03 100644 --- a/src/gen_rules.ml +++ b/src/gen_rules.ml @@ -66,7 +66,7 @@ module Gen(P : Params) = struct in List.map cclibs ~f - let build_lib (lib : Library.t) ~scope ~flags ~dir ~mode ~modules ~dep_graph = + let build_lib (lib : Library.t) ~flags ~dir ~mode ~modules ~dep_graph = Option.iter (Context.compiler ctx mode) ~f:(fun compiler -> let target = lib_archive lib ~dir ~ext:(Mode.compiled_lib_ext mode) in let dep_graph = Ml_kind.Dict.get dep_graph Impl in @@ -107,7 +107,7 @@ module Gen(P : Params) = struct ; A "-a"; A "-o"; Target target ; As stubs_flags ; Dyn (fun (_, cclibs) -> Arg_spec.quote_args "-cclib" (map_cclibs cclibs)) - ; As (List.map lib.library_flags ~f:(SC.expand_vars sctx ~scope ~dir)) + ; As (List.map lib.library_flags ~f:(SC.expand_vars sctx ~scope:lib.scope ~dir)) ; As (match lib.kind with | Normal -> [] | Ppx_deriver | Ppx_rewriter -> ["-linkall"]) @@ -131,7 +131,7 @@ module Gen(P : Params) = struct (Dep ctx.ocamlc) [ As (Utils.g ()) ; Dyn (fun (c_flags, libs) -> - S [ Lib.c_include_flags libs + S [ Lib.c_include_flags ~context:ctx.name ~scope:lib.scope libs ; Arg_spec.quote_args "-ccopt" c_flags ]) ; A "-o"; Target dst @@ -159,7 +159,7 @@ module Gen(P : Params) = struct [ S [A "-I"; Path ctx.stdlib_dir] ; As (SC.cxx_flags sctx) ; Dyn (fun (cxx_flags, libs) -> - S [ Lib.c_include_flags libs + S [ Lib.c_include_flags ~context:ctx.name ~scope:lib.scope libs ; As cxx_flags ]) ; A "-o"; Target dst @@ -176,7 +176,7 @@ module Gen(P : Params) = struct let alias_module_build_sandbox = Scanf.sscanf ctx.version "%u.%u" (fun a b -> a, b) <= (4, 02) - let library_rules (lib : Library.t) ~dir ~all_modules ~files ~scope = + let library_rules (lib : Library.t) ~dir ~all_modules ~files = let dep_kind = if lib.optional then Build.Optional else Required in let flags = Ocaml_flags.make lib.buildable in let modules = @@ -225,7 +225,7 @@ module Gen(P : Params) = struct SC.PP.pped_modules sctx ~dir ~dep_kind ~modules ~preprocess:lib.buildable.preprocess ~preprocessor_deps:lib.buildable.preprocessor_deps ~lib_name:(Some lib.name) - ~scope + ~scope:lib.scope in let modules = match alias_module with @@ -268,7 +268,7 @@ module Gen(P : Params) = struct let dynlink = lib.dynlink in let js_of_ocaml = lib.buildable.js_of_ocaml in Module_compilation.build_modules sctx - ~js_of_ocaml ~dynlink ~flags ~dir ~dep_graph ~modules ~requires ~alias_module; + ~js_of_ocaml ~dynlink ~flags ~scope:lib.scope ~dir ~dep_graph ~modules ~requires ~alias_module; Option.iter alias_module ~f:(fun m -> let flags = Ocaml_flags.default () in Module_compilation.build_module sctx m @@ -276,6 +276,7 @@ module Gen(P : Params) = struct ~dynlink ~sandbox:alias_module_build_sandbox ~flags:{ flags with common = flags.common @ ["-w"; "-49"] } + ~scope:lib.scope ~dir ~modules:(String_map.singleton m.name m) ~dep_graph:(Ml_kind.Dict.make_both (Build.return (String_map.singleton m.name []))) @@ -362,7 +363,7 @@ module Gen(P : Params) = struct Path.relative dir (header ^ ".h"))); List.iter Mode.all ~f:(fun mode -> - build_lib lib ~scope ~flags ~dir ~mode ~modules ~dep_graph); + build_lib lib ~flags ~dir ~mode ~modules ~dep_graph); (* Build *.cma.js *) SC.add_rules sctx ( let src = lib_archive lib ~dir ~ext:(Mode.compiled_lib_ext Mode.Byte) in @@ -412,7 +413,7 @@ module Gen(P : Params) = struct | Executables stuff | +-----------------------------------------------------------------+ *) - let build_exe ~js_of_ocaml ~flags ~dir ~requires ~name ~mode ~modules ~dep_graph + let build_exe ~js_of_ocaml ~flags ~scope ~dir ~requires ~name ~mode ~modules ~dep_graph ~link_flags ~force_custom_bytecode = let exe_ext = Mode.exe_ext mode in let mode, link_flags, compiler = @@ -442,7 +443,7 @@ module Gen(P : Params) = struct [ Ocaml_flags.get flags mode ; A "-o"; Target exe ; As link_flags - ; Dyn (fun (libs, _) -> Lib.link_flags libs ~mode) + ; Dyn (fun (libs, _) -> Lib.link_flags libs ~context:ctx.name ~scope ~mode) ; Dyn (fun (_, cm_files) -> Deps cm_files) ]); if mode = Mode.Byte then @@ -488,12 +489,12 @@ module Gen(P : Params) = struct (* CR-someday jdimino: this should probably say [~dynlink:false] *) Module_compilation.build_modules sctx ~js_of_ocaml:exes.buildable.js_of_ocaml - ~dynlink:true ~flags ~dir ~dep_graph ~modules + ~dynlink:true ~flags ~scope ~dir ~dep_graph ~modules ~requires ~alias_module:None; List.iter exes.names ~f:(fun name -> List.iter Mode.all ~f:(fun mode -> - build_exe ~js_of_ocaml:exes.buildable.js_of_ocaml ~flags ~dir ~requires ~name + build_exe ~js_of_ocaml:exes.buildable.js_of_ocaml ~flags ~scope ~dir ~requires ~name ~mode ~modules ~dep_graph ~link_flags:exes.link_flags ~force_custom_bytecode:(mode = Native && not exes.modes.native))); { Merlin. @@ -694,13 +695,12 @@ Add it to your jbuild file to remove this warning. match (stanza : Stanza.t) with | Library lib -> Some (library_rules lib ~dir - ~all_modules:(Lazy.force all_modules) ~files:(Lazy.force files) - ~scope) + ~all_modules:(Lazy.force all_modules) ~files:(Lazy.force files)) | Executables exes -> Some (executables_rules exes ~dir ~all_modules:(Lazy.force all_modules) ~scope) | _ -> None) - |> Merlin.add_rules sctx ~dir:ctx_dir + |> Merlin.add_rules sctx ~scope ~dir:ctx_dir let () = List.iter (SC.stanzas sctx) ~f:rules let () = @@ -845,10 +845,20 @@ Add it to your jbuild file to remove this warning. sprintf "" (Path.to_string ctx.build_dir)) in + let public_interfaces = + Ordered_set_lang.eval_with_standard lib.public_interfaces + ~standard:(List.map modules ~f:(fun s -> s.Module.name)) + |> String_set.of_list + in List.concat [ List.concat_map modules ~f:(fun m -> + let intf = + if String_set.mem m.Module.name public_interfaces + then [ Module.cm_file m ~dir Cmi ] + else [] + in List.concat - [ [ Module.cm_file m ~dir Cmi ] + [ intf ; if_ native [ Module.cm_file m ~dir Cmx ] ; List.filter_map Ml_kind.all ~f:(Module.cmt_file m ~dir) ; [ match Module.file m ~dir Intf with @@ -894,7 +904,7 @@ Add it to your jbuild file to remove this warning. in let ppx_exe = SC.PP.get_ppx_driver sctx pps - ~dir ~dep_kind:(if lib.optional then Build.Optional else Required) + ~scope:lib.scope ~dir ~dep_kind:(if lib.optional then Build.Optional else Required) in [ppx_exe] in diff --git a/src/install.ml b/src/install.ml index 35490568..b405b7bf 100644 --- a/src/install.ml +++ b/src/install.ml @@ -128,6 +128,8 @@ module Entry = struct Path.relative main_dir dst end +let lib_install_path ~package = Path.relative Entry.Paths.lib package.Package.name + module SMap = Map.Make(Section) let files entries = diff --git a/src/install.mli b/src/install.mli index deb30a63..60dae7c0 100644 --- a/src/install.mli +++ b/src/install.mli @@ -33,3 +33,5 @@ end val files : Entry.t list -> Path.Set.t val gen_install_file : Entry.t list -> string + +val lib_install_path: package:Package.t -> Path.t diff --git a/src/jbuild.ml b/src/jbuild.ml index e3b102b1..5bbe3163 100644 --- a/src/jbuild.ml +++ b/src/jbuild.ml @@ -70,6 +70,9 @@ module Scope = struct ; root : Path.t } + let compare t1 t2 = Path.compare t1.root t2.root + let name t = Option.value ~default:"[root]" t.name + let empty = { name = None ; packages = String_map.empty @@ -523,6 +526,7 @@ module Library = struct type t = { name : string + ; scope : Scope.t ; public : Public_lib.t option ; synopsis : string option ; install_c_headers : string list @@ -541,6 +545,7 @@ module Library = struct ; optional : bool ; buildable : Buildable.t ; dynlink : bool + ; public_interfaces : Ordered_set_lang.t } let v1 pkgs = @@ -564,8 +569,10 @@ module Library = struct field_b "optional" >>= fun optional -> field "self_build_stubs_archive" (option string) ~default:None >>= fun self_build_stubs_archive -> field_b "no_dynlink" >>= fun no_dynlink -> + field_osl "public_interfaces" >>= fun public_interfaces -> return { name + ; scope = pkgs ; public ; synopsis ; install_c_headers @@ -584,6 +591,7 @@ module Library = struct ; optional ; buildable ; dynlink = not no_dynlink + ; public_interfaces }) let has_stubs t = diff --git a/src/jbuild.mli b/src/jbuild.mli index 711aa064..0f2505c1 100644 --- a/src/jbuild.mli +++ b/src/jbuild.mli @@ -17,6 +17,10 @@ module Scope : sig ; root : Path.t } + val compare : t -> t -> int + val name: t -> string + (** Pretty name *) + val make : Package.t list -> t val empty : t @@ -128,6 +132,7 @@ module Library : sig type t = { name : string + ; scope : Scope.t ; public : Public_lib.t option ; synopsis : string option ; install_c_headers : string list @@ -146,6 +151,7 @@ module Library : sig ; optional : bool ; buildable : Buildable.t ; dynlink : bool + ; public_interfaces : Ordered_set_lang.t } val has_stubs : t -> bool diff --git a/src/lib.ml b/src/lib.ml index 103e65c0..461347bc 100644 --- a/src/lib.ml +++ b/src/lib.ml @@ -22,23 +22,35 @@ end include T module Set = Set.Make(T) -let dir = function - | Internal (dir, _) -> dir +let dir ~context ~scope = function + | Internal (dir, lib) -> + if Jbuild.Scope.compare scope lib.scope = 0 then + dir + else begin + match lib.public with + | Some {sub_dir;package; _} -> + let install_dir = Config.local_install_dir ~context in + Path.relative + (Path.append install_dir (Install.lib_install_path ~package)) + (Option.value ~default:"" sub_dir) + | _ -> code_errorf "The non public library %s is accessed in %s outside its scope." lib.name + (Jbuild.Scope.name scope) + end | External pkg -> pkg.dir -let include_paths ts = +let include_paths ~context ~scope ts = List.fold_left ts ~init:Path.Set.empty ~f:(fun acc t -> - Path.Set.add (dir t) acc) + Path.Set.add (dir ~context ~scope t) acc) -let include_flags ts = - let dirs = include_paths ts in +let include_flags ~context ~scope ts = + let dirs = include_paths ~context ~scope ts in Arg_spec.S (List.concat_map (Path.Set.elements dirs) ~f:(fun dir -> [Arg_spec.A "-I"; Path dir])) -let c_include_flags ts = +let c_include_flags ~context ~scope ts = let dirs = List.fold_left ts ~init:Path.Set.empty ~f:(fun acc t -> - Path.Set.add (dir t) acc) + Path.Set.add (dir ~context ~scope t) acc) in Arg_spec.S (List.concat_map (Path.Set.elements dirs) ~f:(fun dir -> [Arg_spec.A "-I"; Path dir])) @@ -52,9 +64,9 @@ let describe = function | External pkg -> sprintf "%s (external)" pkg.name -let link_flags ts ~mode = +let link_flags ~context ~scope ts ~mode = Arg_spec.S - (include_flags ts :: + (include_flags ~context ~scope ts :: List.map ts ~f:(fun t -> match t with | External pkg -> diff --git a/src/lib.mli b/src/lib.mli index 2b43d611..0bf28155 100644 --- a/src/lib.mli +++ b/src/lib.mli @@ -12,13 +12,22 @@ module Set : Set.S with type elt := t (*val deps : t -> string list*) -val include_paths : t list -> Path.Set.t +val include_paths : + context:string -> scope:Jbuild.Scope.t -> + t list -> Path.Set.t +(** The scope given is the current one *) -val include_flags : t list -> _ Arg_spec.t +val include_flags : + context:string -> scope:Jbuild.Scope.t -> + t list -> _ Arg_spec.t -val c_include_flags : t list -> _ Arg_spec.t +val c_include_flags : + context:string -> scope:Jbuild.Scope.t -> + t list -> _ Arg_spec.t -val link_flags : t list -> mode:Mode.t -> _ Arg_spec.t +val link_flags : + context:string -> scope:Jbuild.Scope.t -> + t list -> mode:Mode.t -> _ Arg_spec.t val archive_files : t list -> mode:Mode.t -> ext_lib:string -> Path.t list diff --git a/src/merlin.ml b/src/merlin.ml index 108f300e..2fbec284 100644 --- a/src/merlin.ml +++ b/src/merlin.ml @@ -11,10 +11,10 @@ type t = ; libname : string option } -let ppx_flags sctx ~dir ~src_dir { preprocess; libname; _ } = +let ppx_flags sctx ~scope ~dir ~src_dir { preprocess; libname; _ } = match preprocess with | Pps { pps; flags } -> - let exe = SC.PP.get_ppx_driver sctx pps ~dir ~dep_kind:Optional in + let exe = SC.PP.get_ppx_driver sctx pps ~scope ~dir ~dep_kind:Optional in let command = List.map (Path.reach exe ~from:src_dir :: "--as-ppx" @@ -26,7 +26,7 @@ let ppx_flags sctx ~dir ~src_dir { preprocess; libname; _ } = [sprintf "FLG -ppx \"%s\"" command] | _ -> [] -let dot_merlin sctx ~dir ({ requires; flags; _ } as t) = +let dot_merlin sctx ~scope ~dir ({ requires; flags; _ } as t) = match Path.extract_build_context dir with | Some (_, remaindir) -> let path = Path.relative remaindir ".merlin" in @@ -37,7 +37,7 @@ let dot_merlin sctx ~dir ({ requires; flags; _ } as t) = SC.add_rule sctx ( requires >>^ (fun libs -> - let ppx_flags = ppx_flags sctx ~dir ~src_dir:remaindir t in + let ppx_flags = ppx_flags sctx ~scope ~dir ~src_dir:remaindir t in let internals, externals = List.fold_left libs ~init:([], []) ~f:(fun (internals, externals) -> function @@ -94,8 +94,8 @@ let merge_two a b = | None -> b.libname } -let add_rules sctx ~dir ts = +let add_rules sctx ~scope ~dir ts = if (SC.context sctx).merlin then match ts with | [] -> () - | t :: ts -> dot_merlin sctx ~dir (List.fold_left ts ~init:t ~f:merge_two) + | t :: ts -> dot_merlin sctx ~scope ~dir (List.fold_left ts ~init:t ~f:merge_two) diff --git a/src/merlin.mli b/src/merlin.mli index 50f3f486..28872117 100644 --- a/src/merlin.mli +++ b/src/merlin.mli @@ -8,5 +8,4 @@ type t = } (** Add rules for generating the .merlin in a directory *) -val add_rules : Super_context.t -> dir:Path.t -> t list -> unit - +val add_rules : Super_context.t -> scope:Jbuild.Scope.t -> dir:Path.t -> t list -> unit diff --git a/src/module_compilation.ml b/src/module_compilation.ml index b4c62296..3d850b9c 100644 --- a/src/module_compilation.ml +++ b/src/module_compilation.ml @@ -5,7 +5,7 @@ open! No_io module SC = Super_context let build_cm sctx ?sandbox ~dynlink ~flags ~cm_kind ~(dep_graph:Ocamldep.dep_graph) - ~requires ~(modules : Module.t String_map.t) ~dir ~alias_module (m : Module.t) = + ~requires ~(modules : Module.t String_map.t) ~scope ~dir ~alias_module (m : Module.t) = let ctx = SC.context sctx in Option.iter (Mode.of_cm_kind cm_kind |> Context.compiler ctx) ~f:(fun compiler -> Option.iter (Module.cm_source ~dir m cm_kind) ~f:(fun src -> @@ -66,7 +66,7 @@ let build_cm sctx ?sandbox ~dynlink ~flags ~cm_kind ~(dep_graph:Ocamldep.dep_gra ~extra_targets [ Ocaml_flags.get_for_cm flags ~cm_kind ; cmt_args - ; Dyn Lib.include_flags + ; Dyn (Lib.include_flags ~context:ctx.name ~scope) ; As extra_args ; if dynlink || cm_kind <> Cmx then As [] else A "-nodynlink" ; A "-no-alias-deps" @@ -78,17 +78,17 @@ let build_cm sctx ?sandbox ~dynlink ~flags ~cm_kind ~(dep_graph:Ocamldep.dep_gra ; A "-c"; Ml_kind.flag ml_kind; Dep src ]))) -let build_module sctx ?sandbox ~dynlink ~js_of_ocaml ~flags m ~dir ~dep_graph +let build_module sctx ?sandbox ~dynlink ~js_of_ocaml ~flags m ~scope ~dir ~dep_graph ~modules ~requires ~alias_module = List.iter Cm_kind.all ~f:(fun cm_kind -> let requires = Cm_kind.Dict.get requires cm_kind in - build_cm sctx ?sandbox ~dynlink ~flags ~dir ~dep_graph ~modules m ~cm_kind + build_cm sctx ?sandbox ~dynlink ~flags ~scope ~dir ~dep_graph ~modules m ~cm_kind ~requires ~alias_module); (* Build *.cmo.js *) let src = Module.cm_file m ~dir Cm_kind.Cmo in SC.add_rules sctx (Js_of_ocaml_rules.build_cm sctx ~dir ~js_of_ocaml ~src) -let build_modules sctx ~dynlink ~js_of_ocaml ~flags ~dir ~dep_graph ~modules ~requires +let build_modules sctx ~dynlink ~js_of_ocaml ~flags ~scope ~dir ~dep_graph ~modules ~requires ~alias_module = let cmi_requires = Build.memoize "cmi library dependencies" @@ -113,5 +113,5 @@ let build_modules sctx ~dynlink ~js_of_ocaml ~flags ~dir ~dep_graph ~modules ~re | None -> modules | Some (m : Module.t) -> String_map.remove m.name modules) ~f:(fun ~key:_ ~data:m -> - build_module sctx m ~dynlink ~js_of_ocaml ~flags ~dir ~dep_graph ~modules ~requires + build_module sctx m ~dynlink ~js_of_ocaml ~flags ~scope ~dir ~dep_graph ~modules ~requires ~alias_module) diff --git a/src/module_compilation.mli b/src/module_compilation.mli index 028c774e..a1e1da6f 100644 --- a/src/module_compilation.mli +++ b/src/module_compilation.mli @@ -13,6 +13,7 @@ val build_module -> js_of_ocaml:Jbuild.Js_of_ocaml.t -> flags:Ocaml_flags.t -> Module.t + -> scope:Jbuild.Scope.t -> dir:Path.t -> dep_graph:Ocamldep.dep_graph -> modules:Module.t String_map.t @@ -26,6 +27,7 @@ val build_modules -> dynlink:bool -> js_of_ocaml:Jbuild.Js_of_ocaml.t -> flags:Ocaml_flags.t + -> scope:Jbuild.Scope.t -> dir:Path.t -> dep_graph:Ocamldep.dep_graph -> modules:Module.t String_map.t diff --git a/src/odoc.ml b/src/odoc.ml index 912fdfc4..5ebe0aa4 100644 --- a/src/odoc.ml +++ b/src/odoc.ml @@ -133,7 +133,7 @@ let setup_library_rules sctx (lib : Library.t) ~dir ~modules ~requires requires >>> SC.Libs.file_deps sctx ~ext:odoc_ext - >>^ Lib.include_flags + >>^ Lib.include_flags ~context:context.name ~scope:lib.scope in let modules_and_odoc_files = List.map (String_map.values modules) diff --git a/src/super_context.ml b/src/super_context.ml index f0179ba1..5812f1ae 100644 --- a/src/super_context.ml +++ b/src/super_context.ml @@ -724,7 +724,7 @@ module PP = struct let migrate_driver_main = "ocaml-migrate-parsetree.driver-main" - let build_ppx_driver sctx ~dir ~dep_kind ~target pp_names ~driver = + let build_ppx_driver sctx ~scope ~dir ~dep_kind ~target pp_names ~driver = let ctx = sctx.context in let mode = Context.best_mode ctx in let compiler = Option.value_exn (Context.compiler ctx mode) in @@ -786,10 +786,10 @@ module PP = struct >>> Build.run ~context:ctx (Dep compiler) [ A "-o" ; Target target - ; Dyn (Lib.link_flags ~mode) + ; Dyn (Lib.link_flags ~context:ctx.name ~scope ~mode) ]) - let get_ppx_driver sctx pps ~dir ~dep_kind = + let get_ppx_driver sctx pps ~scope ~dir ~dep_kind = let driver, names = match List.rev_map pps ~f:Pp.to_string with | [] -> (None, []) @@ -806,7 +806,7 @@ module PP = struct | None -> let ppx_dir = Path.relative sctx.ppx_dir key in let exe = Path.relative ppx_dir "ppx.exe" in - build_ppx_driver sctx names ~dir ~dep_kind ~target:exe ~driver; + build_ppx_driver sctx names ~scope ~dir ~dep_kind ~target:exe ~driver; Hashtbl.add sctx.ppx_drivers ~key ~data:exe; exe @@ -878,7 +878,7 @@ module PP = struct ~targets:(Static [dst]) ~scope)) | Pps { pps; flags } -> - let ppx_exe = get_ppx_driver sctx pps ~dir ~dep_kind in + let ppx_exe = get_ppx_driver sctx pps ~scope ~dir ~dep_kind in pped_module m ~dir ~f:(fun kind src dst -> add_rule sctx (preprocessor_deps diff --git a/src/super_context.mli b/src/super_context.mli index ea561e55..74209e2a 100644 --- a/src/super_context.mli +++ b/src/super_context.mli @@ -158,6 +158,7 @@ module PP : sig val get_ppx_driver : t -> Pp.t list + -> scope:Scope.t -> dir:Path.t -> dep_kind:Build.lib_dep_kind -> Path.t diff --git a/test/jbuild b/test/jbuild index 0265ed50..90ea8d66 100644 --- a/test/jbuild +++ b/test/jbuild @@ -104,3 +104,15 @@ (deps ((alias sleep5) (alias sleep4-and-fail) (alias sleep1-and-fail))))) + +(alias + ((name runtest) + (deps ((files_recursively_in workspaces/public_interfaces))) + (action + (chdir workspaces/public_interfaces + (progn + (run ${exe:run.exe} -log log1 -- + ${bin:jbuilder} build --verbose -j1 @install --root . --only good,mylib,mylib2) + (run ${exe:run.exe} -log log2 -inverse -- + ${bin:jbuilder} build -j1 @install --root . --only bad,mylib,mylib2 + )))))) diff --git a/test/workspaces/public_interfaces/bad/bad.opam b/test/workspaces/public_interfaces/bad/bad.opam new file mode 100644 index 00000000..e69de29b diff --git a/test/workspaces/public_interfaces/bad/jbuild b/test/workspaces/public_interfaces/bad/jbuild new file mode 100644 index 00000000..e280de9d --- /dev/null +++ b/test/workspaces/public_interfaces/bad/jbuild @@ -0,0 +1,5 @@ +(library ( + (name bad) + (public_name bad) + (libraries (mylib)) +)) diff --git a/test/workspaces/public_interfaces/bad/main.ml b/test/workspaces/public_interfaces/bad/main.ml new file mode 100644 index 00000000..1754772b --- /dev/null +++ b/test/workspaces/public_interfaces/bad/main.ml @@ -0,0 +1 @@ +let () = Printf.printf "%s" Mylib.Bad.v diff --git a/test/workspaces/public_interfaces/good/good.opam b/test/workspaces/public_interfaces/good/good.opam new file mode 100644 index 00000000..e69de29b diff --git a/test/workspaces/public_interfaces/good/jbuild b/test/workspaces/public_interfaces/good/jbuild new file mode 100644 index 00000000..bc2cdec1 --- /dev/null +++ b/test/workspaces/public_interfaces/good/jbuild @@ -0,0 +1,5 @@ +(library ( + (name good) + (public_name good) + (libraries (mylib mylib2.see_private)) +)) diff --git a/test/workspaces/public_interfaces/good/main.ml b/test/workspaces/public_interfaces/good/main.ml new file mode 100644 index 00000000..3ce783ce --- /dev/null +++ b/test/workspaces/public_interfaces/good/main.ml @@ -0,0 +1 @@ +let () = Printf.printf "%s (and bad size is %i)" Mylib.Good.v Mylib2_see_private.See_private.nb_bad diff --git a/test/workspaces/public_interfaces/mylib/bad.ml b/test/workspaces/public_interfaces/mylib/bad.ml new file mode 100644 index 00000000..b8d9ba48 --- /dev/null +++ b/test/workspaces/public_interfaces/mylib/bad.ml @@ -0,0 +1 @@ +let v = "Bad" diff --git a/test/workspaces/public_interfaces/mylib/good.ml b/test/workspaces/public_interfaces/mylib/good.ml new file mode 100644 index 00000000..a84f3e34 --- /dev/null +++ b/test/workspaces/public_interfaces/mylib/good.ml @@ -0,0 +1 @@ +let v = "Good" diff --git a/test/workspaces/public_interfaces/mylib/jbuild b/test/workspaces/public_interfaces/mylib/jbuild new file mode 100644 index 00000000..2f179011 --- /dev/null +++ b/test/workspaces/public_interfaces/mylib/jbuild @@ -0,0 +1,13 @@ +(library ( + (name mylib) + (public_name mylib) + (modules (good bad)) + (public_interfaces (:standard \ Bad)) +)) + +(library ( + (name mylib2_see_private) + (public_name mylib2.see_private) + (modules (see_private)) + (libraries (mylib)) +)) diff --git a/test/workspaces/public_interfaces/mylib/mylib.opam b/test/workspaces/public_interfaces/mylib/mylib.opam new file mode 100644 index 00000000..e69de29b diff --git a/test/workspaces/public_interfaces/mylib/mylib2.opam b/test/workspaces/public_interfaces/mylib/mylib2.opam new file mode 100644 index 00000000..e69de29b diff --git a/test/workspaces/public_interfaces/mylib/see_private.ml b/test/workspaces/public_interfaces/mylib/see_private.ml new file mode 100644 index 00000000..8fee88c8 --- /dev/null +++ b/test/workspaces/public_interfaces/mylib/see_private.ml @@ -0,0 +1 @@ +let nb_bad = String.length Mylib.Bad.v