• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ocaml / dune / 28976

06 Nov 2024 09:44AM UTC coverage: 6.927% (+0.01%) from 6.913%
28976

push

github

web-flow
fix: Add or remove dune from package sets to allow resolving packages depending on it (#11103)

* fix: Add `dune` to existing packages to allow resolving

Signed-off-by: Marek Kubica <marek@tarides.com>

* Alternate solution which removes `dune` from formulas

Signed-off-by: Marek Kubica <marek@tarides.com>

* chore: leave a comment

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>

* fix(pkg): use correct dune version to evaluate

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>

---------

Signed-off-by: Marek Kubica <marek@tarides.com>
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Co-authored-by: Rudi Grinberg <me@rgrinberg.com>

1 of 6 new or added lines in 2 files covered. (16.67%)

1612 existing lines in 28 files now uncovered.

2951 of 42601 relevant lines covered (6.93%)

26740.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/dune_rules/module_compilation.ml
1
open Import
2
open Memo.O
3

4
(* Arguments for the compiler to prevent it from being too clever.
5

6
   The compiler creates the cmi when it thinks a .ml file has no corresponding
7
   .mli. However this behavior is a bit racy and doesn't work well when the
8
   extension is not .ml or when the .ml and .mli are in different directories.
9
   This flags makes the compiler think there is a .mli file and will the read
10
   the cmi file rather than create it. *)
11
let force_read_cmi source_file = [ "-intf-suffix"; Path.extension source_file ]
×
12

13
(* Build the cm* if the corresponding source is present, in the case of cmi if
14
   the mli is not present it is added as additional target to the .cmo
15
   generation *)
16

17
let opens modules m =
18
  Command.Args.As (Modules.With_vlib.local_open modules m |> Ocaml_flags.open_flags)
×
19
;;
20

21
let other_cm_files ~opaque ~cm_kind ~obj_dir =
22
  List.concat_map ~f:(fun m ->
×
23
    let cmi_kind = Lib_mode.Cm_kind.cmi cm_kind in
×
24
    let deps = [ Path.build (Obj_dir.Module.cm_file_exn obj_dir m ~kind:cmi_kind) ] in
×
25
    if Module.has m ~ml_kind:Impl && cm_kind = Ocaml Cmx && not opaque
×
26
    then (
×
27
      let cmx = Obj_dir.Module.cm_file_exn obj_dir m ~kind:(Ocaml Cmx) in
28
      Path.build cmx :: deps)
×
29
    else if Module.has m ~ml_kind:Impl && cm_kind = Melange Cmj
×
30
    then (
×
31
      let cmj = Obj_dir.Module.cm_file_exn obj_dir m ~kind:(Melange Cmj) in
32
      Path.build cmj :: deps)
×
33
    else deps)
×
34
;;
35

36
let copy_interface ~sctx ~dir ~obj_dir ~cm_kind m =
37
  (* symlink the .cmi into the public interface directory *)
38
  Memo.when_
×
39
    (Module.visibility m <> Visibility.Private
×
40
     && Obj_dir.need_dedicated_public_dir obj_dir)
×
41
    (fun () ->
42
      let cmi_kind = Lib_mode.Cm_kind.cmi cm_kind in
×
43
      Super_context.add_rule
×
44
        sctx
45
        ~dir
46
        (Action_builder.symlink
47
           ~src:(Path.build (Obj_dir.Module.cm_file_exn obj_dir m ~kind:cmi_kind))
×
48
           ~dst:(Obj_dir.Module.cm_public_file_exn obj_dir m ~kind:cmi_kind)))
×
49
;;
50

51
let melange_args (cctx : Compilation_context.t) (cm_kind : Lib_mode.Cm_kind.t) module_ =
52
  match cm_kind with
×
53
  | Ocaml (Cmi | Cmo | Cmx) | Melange Cmi -> []
×
54
  | Melange Cmj ->
×
55
    let bs_package_name, bs_package_output =
56
      let package_output =
57
        Module.file ~ml_kind:Impl module_ |> Option.value_exn |> Path.parent_exn
×
58
      in
59
      match Compilation_context.melange_package_name cctx with
×
60
      | None -> [], package_output
×
61
      | Some lib_name ->
×
62
        let dir =
63
          let package_output = Path.as_in_build_dir_exn package_output in
64
          let lib_root_dir = Path.build (Compilation_context.dir cctx) in
×
65
          let src_dir = Path.build package_output in
×
66
          let build_dir =
×
67
            Compilation_context.super_context cctx
68
            |> Super_context.context
×
69
            |> Context.build_dir
×
70
          in
71
          Path.drop_prefix_exn src_dir ~prefix:lib_root_dir
×
72
          |> Path.Local.to_string
×
73
          |> Path.Build.relative build_dir
×
74
        in
75
        ( [ Command.Args.A "--bs-package-name"; A (Lib_name.to_string lib_name) ]
×
76
        , Path.build dir )
×
77
    in
78
    Command.Args.A "--bs-stop-after-cmj"
79
    :: A "--bs-package-output"
80
    :: Command.Args.Path bs_package_output
81
    :: A "--bs-module-name"
82
    :: A (Melange.js_basename module_)
×
83
    :: bs_package_name
84
;;
85

86
let build_cm
87
  cctx
88
  ~force_write_cmi
89
  ~precompiled_cmi
90
  ~cm_kind
91
  (m : Module.t)
92
  ~(phase : Fdo.phase option)
93
  =
94
  if force_write_cmi && precompiled_cmi
×
95
  then Code_error.raise "force_read_cmi and precompiled_cmi are mutually exclusive" [];
×
96
  let sctx = Compilation_context.super_context cctx in
×
97
  let dir = Compilation_context.dir cctx in
×
98
  let obj_dir = Compilation_context.obj_dir cctx in
×
99
  let ctx = Super_context.context sctx in
×
100
  let mode = Lib_mode.of_cm_kind cm_kind in
×
101
  let sandbox =
×
102
    let default = Compilation_context.sandbox cctx in
103
    match Module.kind m with
×
104
    | Root ->
×
105
      (* This is need to guarantee that no local modules shadow the modules
106
         referenced by the root module *)
107
      Sandbox_config.needs_sandboxing
108
    | _ -> default
×
109
  in
110
  let ocaml = Compilation_context.ocaml cctx in
111
  let* compiler =
×
112
    match mode with
113
    | Melange ->
×
114
      let loc = Compilation_context.loc cctx in
115
      let+ melc = Melange_binary.melc sctx ~loc ~dir in
×
116
      Some melc
×
117
    | Ocaml mode ->
×
118
      Memo.return
×
119
        (let compiler = Ocaml_toolchain.compiler ocaml mode in
120
         (* TODO one day remove this silly optimization *)
121
         match compiler with
×
122
         | Ok _ as s -> Some s
×
123
         | Error _ -> None)
×
124
  in
125
  (let open Option.O in
×
126
   let* compiler = compiler in
127
   let ml_kind = Lib_mode.Cm_kind.source cm_kind in
×
128
   let+ src = Module.file m ~ml_kind in
×
129
   let dst = Obj_dir.Module.cm_file_exn obj_dir m ~kind:cm_kind in
×
130
   let obj =
×
131
     Obj_dir.Module.obj_file obj_dir m ~kind:(Ocaml Cmx) ~ext:ocaml.lib_config.ext_obj
132
   in
133
   let open Memo.O in
×
134
   let* extra_args, extra_deps, other_targets =
135
     if precompiled_cmi
136
     then Memo.return (force_read_cmi src, [], [])
×
137
     else (
×
138
       (* If we're compiling an implementation, then the cmi is present *)
139
       let public_vlib_module = Module.kind m = Impl_vmodule in
×
140
       match phase with
141
       | Some Emit -> Memo.return ([], [], [])
×
142
       | Some Compile | Some All | None ->
×
143
         (match cm_kind, Module.file m ~ml_kind:Intf, public_vlib_module with
×
144
          (* If there is no mli, [ocamlY -c file.ml] produces both the .cmY and
145
             .cmi. We choose to use ocamlc to produce the cmi and to produce the
146
             cmx we have to wait to avoid race conditions. *)
147
          | (Ocaml Cmo | Melange Cmj), None, false ->
×
148
            if force_write_cmi
149
            then Memo.return ([ "-intf-suffix"; ".dummy-ignore-mli" ], [], [])
×
150
            else
151
              let+ () = copy_interface ~dir ~obj_dir ~sctx ~cm_kind m in
×
152
              let cmi_kind = Lib_mode.Cm_kind.cmi cm_kind in
×
153
              [], [], [ Obj_dir.Module.cm_file_exn obj_dir m ~kind:cmi_kind ]
×
154
          | (Ocaml Cmo | Melange Cmj), None, true
×
155
          | (Ocaml (Cmo | Cmx) | Melange Cmj), _, _ ->
×
156
            let cmi_kind = Lib_mode.Cm_kind.cmi cm_kind in
157
            Memo.return
×
158
              ( force_read_cmi src
×
159
              , [ Path.build (Obj_dir.Module.cm_file_exn obj_dir m ~kind:cmi_kind) ]
×
160
              , [] )
161
          | (Ocaml Cmi | Melange Cmi), _, _ ->
×
162
            let+ () = copy_interface ~dir ~obj_dir ~sctx ~cm_kind m in
×
163
            [], [], []))
×
164
   in
165
   let other_targets =
×
166
     match cm_kind with
167
     | Ocaml (Cmi | Cmo) | Melange (Cmi | Cmj) -> other_targets
×
168
     | Ocaml Cmx ->
×
169
       (match phase with
170
        | Some Compile ->
×
171
          let linear =
172
            Obj_dir.Module.obj_file obj_dir m ~kind:(Ocaml Cmx) ~ext:Fdo.linear_ext
173
          in
174
          linear :: other_targets
×
175
        | Some Emit -> other_targets
×
176
        | Some All | None -> obj :: other_targets)
×
177
   in
178
   let opaque = Compilation_context.opaque cctx in
179
   let other_cm_files =
×
180
     let dep_graph = Ml_kind.Dict.get (Compilation_context.dep_graphs cctx) ml_kind in
×
181
     let module_deps = Dep_graph.deps_of dep_graph m in
×
182
     Action_builder.dyn_paths_unit
×
183
       (Action_builder.map module_deps ~f:(other_cm_files ~opaque ~cm_kind ~obj_dir))
×
184
   in
185
   let other_targets, cmt_args =
186
     match cm_kind with
187
     | Ocaml Cmx -> other_targets, Command.Args.empty
×
188
     | Ocaml (Cmi | Cmo) | Melange (Cmi | Cmj) ->
×
189
       if Compilation_context.bin_annot cctx
190
       then (
×
191
         let fn =
192
           Option.value_exn (Obj_dir.Module.cmt_file obj_dir m ~cm_kind ~ml_kind)
×
193
         in
194
         let annots =
×
195
           [ "-bin-annot" ]
196
           @
197
           if Version.supports_bin_annot_occurrences ocaml.version
198
           then [ "-bin-annot-occurrences" ]
×
199
           else []
×
200
         in
201
         fn :: other_targets, As annots)
202
       else other_targets, Command.Args.empty
×
203
   in
204
   let opaque_arg : _ Command.Args.t =
205
     let intf_only = cm_kind = Ocaml Cmi && not (Module.has m ~ml_kind:Impl) in
×
206
     if opaque || (intf_only && Ocaml.Version.supports_opaque_for_mli ocaml.version)
×
207
     then A "-opaque"
×
208
     else Command.Args.empty
×
209
   in
210
   let flags, sandbox =
211
     let flags =
212
       Command.Args.dyn (Ocaml_flags.get (Compilation_context.flags cctx) mode)
×
213
     in
214
     match Module.pp_flags m with
×
215
     | None -> flags, sandbox
×
216
     | Some (pp, sandbox') ->
×
217
       S [ flags; Command.Args.dyn pp ], Sandbox_config.inter sandbox sandbox'
×
218
   in
219
   let output =
220
     match phase with
221
     | Some Compile -> dst
×
222
     | Some Emit -> obj
×
223
     | Some All | None -> dst
×
224
   in
225
   let src =
226
     match phase with
227
     | Some Emit ->
×
228
       let linear_fdo =
229
         Obj_dir.Module.obj_file obj_dir m ~kind:(Ocaml Cmx) ~ext:Fdo.linear_fdo_ext
230
       in
231
       Path.build linear_fdo
×
232
     | Some Compile | Some All | None -> src
×
233
   in
234
   let opens =
235
     let modules = Compilation_context.modules cctx in
236
     opens modules m
×
237
   in
238
   let obj_dirs =
239
     Obj_dir.all_obj_dirs obj_dir ~mode
240
     |> List.concat_map ~f:(fun p -> [ Command.Args.A "-I"; Path (Path.build p) ])
×
241
   in
242
   Super_context.add_rule
×
243
     sctx
244
     ~dir:
245
       (let dune_version =
246
          Compilation_context.scope cctx |> Scope.project |> Dune_project.dune_version
×
247
        in
248
        (* TODO DUNE4 get rid of the old behavior *)
249
        if dune_version >= (3, 7) then dir else Context.build_dir ctx)
×
250
     ?loc:(Compilation_context.loc cctx)
×
251
     (let open Action_builder.With_targets.O in
252
      Action_builder.with_no_targets (Action_builder.paths extra_deps)
×
253
      >>> Action_builder.with_no_targets other_cm_files
×
254
      >>> Command.run
×
255
            ~dir:(Path.build (Context.build_dir ctx))
×
256
            compiler
257
            [ flags
258
            ; cmt_args
259
            ; Command.Args.S obj_dirs
260
            ; Command.Args.as_any
×
261
                (Lib_mode.Cm_kind.Map.get (Compilation_context.includes cctx) cm_kind)
×
262
            ; As extra_args
263
            ; S (melange_args cctx cm_kind m)
×
264
            ; A "-no-alias-deps"
265
            ; opaque_arg
266
            ; As (Fdo.phase_flags phase)
×
267
            ; opens
268
            ; As
269
                (match Compilation_context.stdlib cctx with
270
                 | None -> []
×
271
                 | Some _ ->
×
272
                   (* XXX why aren't these just normal library flags? *)
273
                   [ "-nopervasives"; "-nostdlib" ])
274
            ; A "-o"
275
            ; Target output
276
            ; A "-c"
277
            ; Command.Ml_kind.flag ml_kind
×
278
            ; Dep src
279
            ; Hidden_targets other_targets
280
            ]
281
      >>| Action.Full.add_sandbox sandbox))
×
282
  |> Memo.Option.iter ~f:Fun.id
283
;;
284

285
let build_module ?(force_write_cmi = false) ?(precompiled_cmi = false) cctx m =
×
286
  let open Memo.O in
×
287
  let { Lib_mode.Map.ocaml; melange } = Compilation_context.modes cctx in
288
  let build_cm = build_cm cctx m ~force_write_cmi ~precompiled_cmi in
×
289
  let* () =
×
290
    Memo.when_ (ocaml.byte || ocaml.native) (fun () ->
×
291
      let* () = build_cm ~cm_kind:(Ocaml Cmo) ~phase:None
×
292
      and* () =
293
        let ctx = Compilation_context.context cctx in
294
        let ocaml = Compilation_context.ocaml cctx in
×
295
        let can_split =
×
296
          Ocaml.Version.supports_split_at_emit ocaml.version
×
297
          || Ocaml_config.is_dev_version ocaml.ocaml_config
×
298
        in
299
        match Context.fdo_target_exe ctx, can_split with
×
300
        | None, _ -> build_cm ~cm_kind:(Ocaml Cmx) ~phase:None
×
301
        | Some _, false -> build_cm ~cm_kind:(Ocaml Cmx) ~phase:(Some All)
×
302
        | Some _, true ->
×
303
          build_cm ~cm_kind:(Ocaml Cmx) ~phase:(Some Compile)
304
          >>> Fdo.opt_rule cctx m
×
305
          >>> build_cm ~cm_kind:(Ocaml Cmx) ~phase:(Some Emit)
×
306
      and* () =
307
        Memo.when_ (not precompiled_cmi) (fun () ->
×
308
          build_cm ~cm_kind:(Ocaml Cmi) ~phase:None)
×
309
      in
310
      let obj_dir = Compilation_context.obj_dir cctx in
×
311
      match Obj_dir.Module.cm_file obj_dir m ~kind:(Ocaml Cmo) with
×
312
      | None -> Memo.return ()
×
313
      | Some src ->
×
314
        Memo.parallel_iter Js_of_ocaml.Mode.all ~f:(fun mode ->
315
          Compilation_context.js_of_ocaml cctx
×
UNCOV
316
          |> Js_of_ocaml.Mode.Pair.select ~mode
×
317
          |> Memo.Option.iter ~f:(fun in_context ->
×
318
            (* Build *.cmo.js / *.wasmo *)
319
            let sctx = Compilation_context.super_context cctx in
×
UNCOV
320
            let dir = Compilation_context.dir cctx in
×
UNCOV
321
            let action_with_targets =
×
322
              Jsoo_rules.build_cm
323
                sctx
324
                ~dir
325
                ~in_context
326
                ~mode
UNCOV
327
                ~src:(Path.build src)
×
328
                ~obj_dir
329
                ~config:None
330
            in
331
            Super_context.add_rule sctx ~dir action_with_targets)))
×
332
  in
333
  Memo.when_ melange (fun () ->
×
UNCOV
334
    let* () = build_cm ~cm_kind:(Melange Cmj) ~phase:None in
×
UNCOV
335
    Memo.when_ (not precompiled_cmi) (fun () ->
×
UNCOV
336
      build_cm ~cm_kind:(Melange Cmi) ~phase:None))
×
337
;;
338

339
let ocamlc_i ~deps cctx (m : Module.t) ~output =
340
  let sctx = Compilation_context.super_context cctx in
×
341
  let obj_dir = Compilation_context.obj_dir cctx in
×
342
  let dir = Compilation_context.dir cctx in
×
343
  let ctx = Super_context.context sctx in
×
UNCOV
344
  let src = Option.value_exn (Module.file m ~ml_kind:Impl) in
×
UNCOV
345
  let sandbox = Compilation_context.sandbox cctx in
×
346
  let cm_deps =
×
347
    Action_builder.dyn_paths_unit
348
      (let open Action_builder.O in
UNCOV
349
       let+ deps = Ml_kind.Dict.get deps Impl in
×
350
       List.concat_map deps ~f:(fun m ->
×
351
         [ Path.build (Obj_dir.Module.cm_file_exn obj_dir m ~kind:(Ocaml Cmi)) ]))
×
352
  in
353
  let ocaml_flags = Ocaml_flags.get (Compilation_context.flags cctx) (Ocaml Byte) in
×
UNCOV
354
  let modules = Compilation_context.modules cctx in
×
UNCOV
355
  let ocaml = Compilation_context.ocaml cctx in
×
356
  Super_context.add_rule
×
357
    sctx
358
    ~dir
359
    (Action_builder.With_targets.add
×
360
       ~file_targets:[ output ]
361
       (let open Action_builder.With_targets.O in
362
        Action_builder.with_no_targets cm_deps
×
UNCOV
363
        >>> Command.run
×
364
              (Ok ocaml.ocamlc)
UNCOV
365
              ~dir:(Path.build (Context.build_dir ctx))
×
366
              ~stdout_to:output
367
              [ Command.Args.dyn ocaml_flags
×
368
              ; A "-I"
369
              ; Path (Path.build (Obj_dir.byte_dir obj_dir))
×
UNCOV
370
              ; Command.Args.as_any
×
371
                  (Lib_mode.Cm_kind.Map.get
×
UNCOV
372
                     (Compilation_context.includes cctx)
×
373
                     (Ocaml Cmo))
374
              ; opens modules m
×
375
              ; A "-short-paths"
376
              ; A "-i"
377
              ; Command.Ml_kind.flag Impl
×
378
              ; Dep src
379
              ]
UNCOV
380
        >>| Action.Full.add_sandbox sandbox))
×
381
;;
382

383
module Alias_module = struct
384
  (* The alias module is an implementation detail to support wrapping library
385
     modules under a single toplevel name. Since OCaml doesn't have proper
386
     support for namespacing at the moment, in order to expose module `X` of
387
     library `foo` as `Foo.X`, Dune does the following:
388

389
     - it compiles x.ml to Foo__X.cmo, Foo__X.cmx, Foo__X.o, ... - it implicitly
390
       exposes a module alias [module X = Foo__X] to all the modules of the `foo`
391
       library
392

393
     The second point is achieved by implicitly opening a module containing such
394
     aliases for all modules of `foo` when compiling modules of `foo` via the
395
     `-open` option of the compiler. This module is called the alias module and
396
     is implicitly generated by Dune.*)
397

398
  type alias =
399
    { local_name : Module_name.t
400
    ; canonical_path : Module_name.Path.t
401
    ; obj_name : Module_name.Unique.t
402
    }
403

404
  type t =
405
    { aliases : alias list
406
    ; shadowed : Module_name.t list
407
    }
408

409
  let to_ml { aliases; shadowed } =
410
    let b = Buffer.create 16 in
×
UNCOV
411
    Buffer.add_string b "(* generated by dune *)\n";
×
UNCOV
412
    List.iter aliases ~f:(fun { canonical_path; local_name; obj_name } ->
×
413
      Printf.bprintf
×
414
        b
415
        "\n(** @canonical %s *)"
UNCOV
416
        (Module_name.Path.to_string canonical_path);
×
417
      Printf.bprintf
×
418
        b
419
        "\nmodule %s = %s\n"
420
        (Module_name.to_string local_name)
×
UNCOV
421
        (Module_name.Unique.to_name ~loc:Loc.none obj_name |> Module_name.to_string));
×
UNCOV
422
    List.iter shadowed ~f:(fun shadowed ->
×
423
      Printf.bprintf
×
424
        b
425
        "\nmodule %s = struct end\n[@@deprecated \"this module is shadowed\"]\n"
UNCOV
426
        (Module_name.to_string shadowed));
×
UNCOV
427
    Buffer.contents b
×
428
  ;;
429

430
  let of_modules project modules group =
431
    let aliases =
×
432
      Modules.Group.for_alias group
433
      |> List.map ~f:(fun (local_name, m) ->
×
UNCOV
434
        let canonical_path = Modules.With_vlib.canonical_path modules group m in
×
435
        let obj_name = Module.obj_name m in
×
436
        { canonical_path; local_name; obj_name })
×
437
    in
438
    let shadowed =
×
UNCOV
439
      if Dune_project.dune_version project < (3, 5)
×
440
      then []
×
441
      else (
×
442
        let lib_interface = Modules.Group.lib_interface group in
UNCOV
443
        match Module.kind lib_interface with
×
UNCOV
444
        | Alias _ -> []
×
UNCOV
445
        | _ -> [ Module.name (Modules.Group.alias group) ])
×
446
    in
447
    { aliases; shadowed }
448
  ;;
449
end
450

451
let build_alias_module cctx group =
452
  let alias_file () =
×
UNCOV
453
    let project = Compilation_context.scope cctx |> Scope.project in
×
UNCOV
454
    let modules = Compilation_context.modules cctx in
×
455
    Alias_module.of_modules project modules group |> Alias_module.to_ml
×
456
  in
457
  let alias_module = Modules.Group.alias group in
458
  let cctx = Compilation_context.for_alias_module cctx alias_module in
×
459
  let sctx = Compilation_context.super_context cctx in
×
460
  let file = Option.value_exn (Module.file alias_module ~ml_kind:Impl) in
×
UNCOV
461
  let dir = Compilation_context.dir cctx in
×
UNCOV
462
  let* () =
×
UNCOV
463
    Super_context.add_rule
×
464
      ~loc:Loc.none
465
      sctx
466
      ~dir
467
      (Action_builder.delayed alias_file
468
       |> Action_builder.write_file_dyn (Path.as_in_build_dir_exn file))
×
469
  in
UNCOV
470
  let cctx = Compilation_context.for_alias_module cctx alias_module in
×
UNCOV
471
  build_module cctx alias_module
×
472
;;
473

474
let root_source entries =
UNCOV
475
  let b = Buffer.create 128 in
×
UNCOV
476
  List.iter entries ~f:(fun name ->
×
477
    Printf.bprintf
×
478
      b
479
      "module %s = %s\n"
UNCOV
480
      (Module_name.to_string name)
×
UNCOV
481
      (Module_name.to_string name));
×
UNCOV
482
  Buffer.contents b
×
483
;;
484

485
let build_root_module cctx root_module =
486
  let entries = Compilation_context.root_module_entries cctx in
×
487
  let cctx = Compilation_context.for_root_module cctx root_module in
×
488
  let sctx = Compilation_context.super_context cctx in
×
489
  let file = Option.value_exn (Module.file root_module ~ml_kind:Impl) in
×
UNCOV
490
  let dir = Compilation_context.dir cctx in
×
UNCOV
491
  let* () =
×
UNCOV
492
    Super_context.add_rule
×
493
      ~loc:Loc.none
494
      sctx
495
      ~dir
496
      (let target = Path.as_in_build_dir_exn file in
UNCOV
497
       Action_builder.write_file_dyn
×
498
         target
499
         (let open Action_builder.O in
500
          let+ entries = entries in
UNCOV
501
          root_source entries))
×
502
  in
UNCOV
503
  build_module cctx root_module
×
504
;;
505

506
let build_all cctx =
507
  let for_wrapped_compat = lazy (Compilation_context.for_wrapped_compat cctx) in
×
508
  let modules = Compilation_context.modules cctx in
UNCOV
509
  Memo.parallel_iter
×
510
    (Modules.With_vlib.fold_no_vlib_with_aliases
×
511
       modules
512
       ~init:[]
513
       ~normal:(fun x acc -> `Normal x :: acc)
×
514
       ~alias:(fun group acc -> `Alias group :: acc))
×
515
    ~f:(function
UNCOV
516
      | `Alias group -> build_alias_module cctx group
×
517
      | `Normal m ->
×
518
        (match Module.kind m with
519
         | Alias _ -> assert false
520
         | Root -> build_root_module cctx m
×
521
         | Wrapped_compat ->
×
522
           let cctx = Lazy.force for_wrapped_compat in
UNCOV
523
           build_module cctx m
×
UNCOV
524
         | _ ->
×
525
           let cctx =
526
             if Modules.With_vlib.is_stdlib_alias modules m
527
             then
528
               (* XXX it would probably be simpler if the flags were just for this
529
                  module in the definition of the stanza *)
UNCOV
530
               Compilation_context.for_alias_module cctx m
×
UNCOV
531
             else cctx
×
532
           in
533
           build_module cctx m))
534
;;
535

536
let with_empty_intf ~sctx ~dir module_ =
537
  let name =
×
538
    Module.file module_ ~ml_kind:Impl
539
    |> Option.value_exn
×
UNCOV
540
    |> Path.set_extension ~ext:".mli"
×
541
  in
UNCOV
542
  let rule =
×
543
    Action_builder.write_file
544
      (Path.as_in_build_dir_exn name)
×
545
      "(* Auto-generated by Dune *)"
546
  in
UNCOV
547
  let+ () = Super_context.add_rule sctx ~dir rule in
×
UNCOV
548
  Module.add_file module_ Ml_kind.Intf (Module.File.make Dialect.ocaml name)
×
549
;;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc