Skip to content

Commit a6d7819

Browse files
authored
fix: -H for hidden modules (#12666)
* fix: -H for hidden modules Always make sure that hidden modules are available via -H when the compiler supports this -H flag. Signed-off-by: Rudi Grinberg <[email protected]>
1 parent 9fd6640 commit a6d7819

File tree

9 files changed

+100
-36
lines changed

9 files changed

+100
-36
lines changed

bin/ocaml/top.ml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ let term =
7676
in
7777
let include_paths =
7878
Dune_rules.Lib_flags.L.toplevel_include_paths requires lib_config
79+
|> Dune_rules.Lib_flags.L.include_only
80+
|> Path.Set.of_list
7981
in
8082
let+ files_to_load = files_to_load_of_requires sctx requires in
8183
Dune_rules.Toplevel.print_toplevel_init_file
@@ -134,7 +136,9 @@ module Module = struct
134136
let lib_config = (Compilation_context.ocaml cctx).lib_config in
135137
Dune_rules.Lib_flags.L.toplevel_include_paths requires lib_config
136138
in
137-
Path.Set.add libs (Path.build (Obj_dir.byte_dir private_obj_dir))
139+
Path.Map.set libs (Path.build (Obj_dir.byte_dir private_obj_dir)) Include
140+
|> Dune_rules.Lib_flags.L.include_only
141+
|> Path.Set.of_list
138142
in
139143
let files_to_load () =
140144
let+ libs, modules =

doc/changes/fixed/12666.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Pass private modules with -H when this is available (#12666, @rgrinberg)

src/dune_rules/ctypes/ctypes_rules.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ let build_c_program
221221
Lib.DB.resolve (Scope.libs scope) (Loc.none, ctypes) |> Resolve.Memo.read
222222
in
223223
Lib_flags.L.include_paths [ lib ] (Ocaml Native) ocaml.lib_config
224-
|> Path.Set.to_list
224+
|> Lib_flags.L.include_only
225225
in
226226
let ocaml_where = ocaml.lib_config.stdlib_dir in
227227
ocaml_where :: ctypes_include_dirs

src/dune_rules/lib_flags.ml

Lines changed: 78 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,29 @@ module L = struct
9292
;;
9393

9494
let to_iflags dir = to_flags "-I" dir
95-
let to_hflags dir = to_flags "-H" dir
95+
96+
type flag =
97+
| Hidden
98+
| Include
99+
100+
let to_flags dirs =
101+
Command.Args.S
102+
(Path.Map.foldi dirs ~init:[] ~f:(fun dir flag acc ->
103+
let flag =
104+
match flag with
105+
| Include -> "-I"
106+
| Hidden -> "-H"
107+
in
108+
Command.Args.Path dir :: A flag :: acc)
109+
|> List.rev)
110+
;;
111+
112+
let include_only =
113+
Path.Map.foldi ~init:[] ~f:(fun path flag acc ->
114+
match flag with
115+
| Include -> path :: acc
116+
| Hidden -> acc)
117+
;;
96118

97119
let remove_stdlib dirs (lib_config : Lib_config.t) =
98120
Path.Set.remove dirs lib_config.stdlib_dir
@@ -103,10 +125,36 @@ module L = struct
103125
; melange_emit : bool
104126
}
105127

128+
let combine_flags x y =
129+
match x, y with
130+
| Include, _ | _, Include -> Include
131+
| Hidden, Hidden -> Hidden
132+
;;
133+
134+
let add_flag flags path x =
135+
Path.Map.update flags path ~f:(fun y ->
136+
Some
137+
(match y with
138+
| None -> x
139+
| Some y -> combine_flags x y))
140+
;;
141+
106142
let include_paths =
107-
let add_public_dir ~visible_cmi obj_dir acc mode =
143+
let add_public_dir ocaml ~visible_cmi obj_dir acc mode =
144+
let use_hidden =
145+
Ocaml.Version.supports_hidden_includes ocaml
146+
&&
147+
match mode.lib_mode with
148+
| Ocaml _ -> true
149+
| Melange -> false
150+
in
108151
match visible_cmi with
109-
| false -> acc
152+
| false ->
153+
if use_hidden
154+
then
155+
Obj_dir.all_cmis obj_dir
156+
|> List.fold_left ~init:acc ~f:(fun acc dir -> add_flag acc dir Hidden)
157+
else acc
110158
| true ->
111159
let public_cmi_dirs =
112160
List.map
@@ -116,14 +164,19 @@ module L = struct
116164
| { lib_mode = Melange; melange_emit = false } ->
117165
[ Obj_dir.public_cmi_melange_dir ]
118166
| { lib_mode = Melange; melange_emit = true } ->
119-
(* Add the dir where `.cmj` files exist, even for installed
120-
private libraries. Melange needs to query `.cmj` files for
121-
`import` information *)
167+
(* Add the dir where [.cmj] files exist, even for installed
168+
private libraries. Melange needs to query [.cmj] files for
169+
[import] information *)
122170
[ Obj_dir.melange_dir; Obj_dir.public_cmi_melange_dir ])
123171
in
124-
List.fold_left public_cmi_dirs ~init:acc ~f:Path.Set.add
172+
let acc =
173+
List.fold_left public_cmi_dirs ~init:acc ~f:(fun acc dir ->
174+
add_flag acc dir Include)
175+
in
176+
if use_hidden then add_flag acc (Obj_dir.byte_dir obj_dir) Hidden else acc
125177
in
126-
fun ?project ts mode lib_config ->
178+
fun ?project ts mode (lib_config : Lib_config.t) ->
179+
let ocaml = lib_config.ocaml_version in
127180
let visible_cmi =
128181
match project with
129182
| None -> fun _ -> true
@@ -139,33 +192,37 @@ module L = struct
139192
| _ -> true)
140193
in
141194
let dirs =
142-
List.fold_left ts ~init:Path.Set.empty ~f:(fun acc t ->
195+
List.fold_left ts ~init:Path.Map.empty ~f:(fun acc t ->
143196
let obj_dir = Lib_info.obj_dir (Lib.info t) in
144197
let visible_cmi = visible_cmi t in
145198
match mode.lib_mode with
146-
| Melange -> add_public_dir ~visible_cmi obj_dir acc mode
199+
| Melange -> add_public_dir ocaml ~visible_cmi obj_dir acc mode
147200
| Ocaml ocaml_mode ->
148-
let acc = add_public_dir ~visible_cmi obj_dir acc mode in
201+
let acc = add_public_dir ocaml ~visible_cmi obj_dir acc mode in
149202
(match ocaml_mode with
150203
| Byte -> acc
151204
| Native ->
152205
let native_dir = Obj_dir.native_dir obj_dir in
153-
Path.Set.add acc native_dir))
206+
add_flag acc native_dir Include))
154207
in
155-
remove_stdlib dirs lib_config
208+
Path.Map.remove dirs lib_config.stdlib_dir
156209
;;
157210

158211
let include_flags ?project ~direct_libs ~hidden_libs mode lib_config =
159212
let include_paths ts =
160213
include_paths ?project ts { lib_mode = mode; melange_emit = false }
161214
in
162-
let hidden_includes = to_hflags (include_paths hidden_libs lib_config) in
163-
let direct_includes = to_iflags (include_paths direct_libs lib_config) in
215+
let hidden_includes =
216+
include_paths hidden_libs lib_config
217+
|> Path.Map.map ~f:(fun _ -> Hidden)
218+
|> to_flags
219+
in
220+
let direct_includes = to_flags (include_paths direct_libs lib_config) in
164221
Command.Args.S [ direct_includes; hidden_includes ]
165222
;;
166223

167224
let melange_emission_include_flags ?project ts lib_config =
168-
to_iflags
225+
to_flags
169226
(include_paths ?project ts { lib_mode = Melange; melange_emit = true } lib_config)
170227
;;
171228

@@ -239,9 +296,12 @@ module L = struct
239296
;;
240297

241298
let toplevel_include_paths ts lib_config =
242-
Path.Set.union
299+
Path.Map.union
300+
~f:(fun _ x y -> Some (combine_flags x y))
243301
(include_paths ts (Lib_mode.Ocaml Byte) lib_config)
244-
(toplevel_ld_paths ts lib_config)
302+
(toplevel_ld_paths ts lib_config
303+
|> Path.Set.to_list_map ~f:(fun p -> p, Include)
304+
|> Path.Map.of_list_exn)
245305
;;
246306
end
247307

src/dune_rules/lib_flags.mli

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@ module L : sig
2424

2525
val to_iflags : Path.Set.t -> _ Command.Args.t
2626

27-
val include_paths
28-
: ?project:Dune_project.t
29-
-> t
30-
-> Lib_mode.t
31-
-> Lib_config.t
32-
-> Path.Set.t
27+
type flag =
28+
| Hidden
29+
| Include
30+
31+
type flags := flag Path.Map.t
32+
33+
val include_only : flags -> Path.t list
34+
val to_flags : flags -> _ Command.Args.t
35+
val include_paths : ?project:Dune_project.t -> t -> Lib_mode.t -> Lib_config.t -> flags
3336

3437
val include_flags
3538
: ?project:Dune_project.t
@@ -47,7 +50,7 @@ module L : sig
4750

4851
val c_include_flags : t -> Super_context.t -> _ Command.Args.t
4952
val toplevel_ld_paths : t -> Lib_config.t -> Path.Set.t
50-
val toplevel_include_paths : t -> Lib_config.t -> Path.Set.t
53+
val toplevel_include_paths : t -> Lib_config.t -> flags
5154
end
5255

5356
(** The list of files that will be read by the compiler when linking an

src/dune_rules/mdx.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,8 @@ let mdx_prog_gen t ~sctx ~dir ~scope ~mdx_prog =
426426
let open Command.Args in
427427
S
428428
(Lib_flags.L.include_paths libs_to_include (Ocaml mode) lib_config
429-
|> Path.Set.to_list_map ~f:(fun p -> S [ A "--directory"; Path p ]))
429+
|> Lib_flags.L.include_only
430+
|> List.map ~f:(fun p -> S [ A "--directory"; Path p ]))
430431
in
431432
let open Command.Args in
432433
let prelude_args = S (List.concat_map t.preludes ~f:(Prelude.to_args ~dir)) in

src/dune_rules/ppx_driver.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,7 @@ let build_ppx_driver sctx ~scope ~target ~pps ~pp_names =
281281
Driver.select pps ~loc:(Dot_ppx (target, pp_names))
282282
>>| Resolve.map ~f:(fun driver -> driver, pps)
283283
>>|
284-
(* Extend the dependency stack as we don't have locations at this
285-
point *)
284+
(* Extend the dependency stack as we don't have locations at this point *)
286285
Resolve.push_stack_frame ~human_readable_description:(fun () ->
287286
Dyn.pp (List [ String "pps"; Dyn.(list Lib_name.to_dyn) pp_names ]))
288287
in

src/dune_rules/toplevel.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ let setup_module_rules t =
121121
let requires_compile = Compilation_context.requires_compile t.cctx in
122122
Resolve.Memo.read requires_compile
123123
in
124-
Lib_flags.L.include_paths libs (Ocaml Byte) lib_config |> Path.Set.to_list
124+
Lib_flags.L.include_paths libs (Ocaml Byte) lib_config
125+
|> Lib_flags.L.include_only
125126
in
126127
Source.pp_ml t.source ~include_dirs
127128
in

test/blackbox-tests/test-cases/private-modules/private-module-compilation.t

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,6 @@ Test demonstrating private modules in wrapped library
3636

3737
Build should fail because Secret is private:
3838
$ dune build
39-
File "consumer.ml", line 4, characters 17-40:
40-
4 | print_endline (Mylib.Secret.get_hidden ())
41-
^^^^^^^^^^^^^^^^^^^^^^^
42-
Error: The module Mylib.Secret is an alias for module Mylib__Secret, which is missing
43-
[1]
4439

4540
Now test that removing private_modules makes it work:
4641
$ cat > mylib/dune << EOF

0 commit comments

Comments
 (0)