• 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/exe_rules.ml
1
open Import
2
open Memo.O
3

4
let first_exe (exes : Executables.t) = snd (Nonempty_list.hd exes.names)
×
5

6
let linkages
7
  ~dynamically_linked_foreign_archives
8
  (ocaml : Ocaml_toolchain.t)
9
  ~(exes : Executables.t)
10
  ~explicit_js_mode
11
  ~jsoo_enabled_modes
12
  ~jsoo_is_whole_program
13
  =
UNCOV
14
  let module L = Executables.Link_mode in
×
15
  let l =
16
    let has_native = Result.is_ok ocaml.ocamlopt in
UNCOV
17
    let modes =
×
18
      L.Map.to_list exes.modes
19
      |> List.filter ~f:(fun (mode, _) ->
×
UNCOV
20
        match (mode : Executables.Link_mode.t) with
×
21
        | Jsoo mode -> Js_of_ocaml.Mode.Pair.select ~mode jsoo_enabled_modes
×
UNCOV
22
        | Byte_complete | Other _ -> true)
×
23
      |> List.map ~f:(fun (mode, loc) ->
×
24
        Exe.Linkage.of_user_config ocaml ~dynamically_linked_foreign_archives ~loc mode)
×
25
    in
UNCOV
26
    let modes =
×
27
      if has_native
28
      then modes
×
UNCOV
29
      else List.filter modes ~f:(fun x -> not (Exe.Linkage.is_native x))
×
30
    in
31
    let modes =
32
      if L.Map.existsi ~f:(fun m _ -> L.is_jsoo m) exes.modes
×
33
      then (
×
34
        let jsoo_bytecode_exe_needed =
35
          Js_of_ocaml.Mode.Set.inter jsoo_enabled_modes jsoo_is_whole_program
36
        in
UNCOV
37
        let bytecode_exe_needed =
×
38
          L.Map.existsi
39
            ~f:(fun mode _ ->
40
              match (mode : Executables.Link_mode.t) with
×
41
              | Jsoo mode -> Js_of_ocaml.Mode.Pair.select ~mode jsoo_bytecode_exe_needed
×
UNCOV
42
              | Byte_complete | Other _ -> false)
×
43
            exes.modes
44
        in
UNCOV
45
        if bytecode_exe_needed then Exe.Linkage.byte_for_jsoo :: modes else modes)
×
UNCOV
46
      else if explicit_js_mode
×
47
      then modes
×
48
      else if L.Map.mem exes.modes L.byte
×
49
      then
50
        Exe.Linkage.js
×
51
        ::
52
        (if Js_of_ocaml.Mode.Pair.select ~mode:JS jsoo_is_whole_program
UNCOV
53
         then Exe.Linkage.byte_for_jsoo :: modes
×
UNCOV
54
         else modes)
×
55
      else modes
×
56
    in
57
    modes
58
  in
59
  (* If bytecode was requested but not native or best version, add custom
60
     linking *)
UNCOV
61
  if L.Map.mem exes.modes L.byte
×
62
     && (not (L.Map.mem exes.modes L.native))
×
UNCOV
63
     && not (L.Map.mem exes.modes L.exe)
×
64
  then Exe.Linkage.custom ocaml.version :: l
×
65
  else l
×
66
;;
67

68
let programs ~modules ~(exes : Executables.t) =
69
  List.map (Nonempty_list.to_list exes.names) ~f:(fun (loc, name) ->
×
70
    let mod_name = Module_name.of_string_allow_invalid (loc, name) in
×
UNCOV
71
    match Modules.With_vlib.find modules mod_name with
×
72
    | Some m ->
×
73
      if Module.has m ~ml_kind:Impl
UNCOV
74
      then { Exe.Program.name; main_module_name = mod_name; loc }
×
75
      else
UNCOV
76
        User_error.raise
×
77
          ~loc
UNCOV
78
          [ Pp.textf "Module %S has no implementation." (Module_name.to_string mod_name) ]
×
UNCOV
79
    | None ->
×
80
      let msg =
81
        match Ordered_set_lang.Unexpanded.loc exes.buildable.modules.modules with
UNCOV
82
        | None -> Pp.textf "Module %S doesn't exist." (Module_name.to_string mod_name)
×
UNCOV
83
        | Some _ ->
×
UNCOV
84
          Pp.textf
×
85
            "The name %S is not listed in the (modules) field of this stanza."
86
            (Module_name.to_string mod_name)
×
87
      in
88
      User_error.raise ~loc [ msg ])
89
;;
90

91
let o_files
92
  sctx
93
  ~dir
94
  ~expander
95
  ~(exes : Executables.t)
96
  ~linkages
97
  ~dir_contents
98
  ~requires_compile
99
  =
100
  if not (Executables.has_foreign exes)
×
101
  then Memo.return @@ Mode.Map.empty
×
102
  else (
×
103
    let what =
104
      if List.is_empty exes.buildable.foreign_stubs then "archives" else "stubs"
×
105
    in
106
    if List.exists linkages ~f:Exe.Linkage.is_byte
107
    then
UNCOV
108
      User_error.raise
×
109
        ~loc:exes.buildable.loc
UNCOV
110
        [ Pp.textf "Pure bytecode executables cannot contain foreign %s." what ]
×
111
        ~hints:
UNCOV
112
          [ Pp.text "If you only need to build a native executable use \"(modes exe)\"." ];
×
UNCOV
113
    let* foreign_sources =
×
UNCOV
114
      let+ foreign_sources = Dir_contents.foreign_sources dir_contents in
×
UNCOV
115
      let first_exe = first_exe exes in
×
UNCOV
116
      Foreign_sources.for_exes foreign_sources ~first_exe
×
117
    in
UNCOV
118
    let* foreign_o_files =
×
119
      let+ { Lib_config.ext_obj; _ } =
UNCOV
120
        let+ ocaml = Super_context.context sctx |> Context.ocaml in
×
121
        ocaml.lib_config
×
122
      in
UNCOV
123
      Foreign.Objects.build_paths exes.buildable.extra_objects ~ext_obj ~dir
×
124
    in
UNCOV
125
    let+ o_files =
×
126
      Foreign_rules.build_o_files
127
        ~sctx
128
        ~dir
129
        ~expander
130
        ~requires:requires_compile
131
        ~dir_contents
132
        ~foreign_sources
133
    in
134
    (* [foreign_o_files] are not mode-dependent *)
UNCOV
135
    Mode.Map.Multi.add_all o_files All foreign_o_files)
×
136
;;
137

138
let executables_rules
139
  ~sctx
140
  ~dir
141
  ~expander
142
  ~dir_contents
143
  ~scope
144
  ~compile_info
145
  ~embed_in_plugin_libraries
146
  (exes : Executables.t)
147
  =
148
  (* Use "eobjs" rather than "objs" to avoid a potential conflict with a library
149
     of the same name *)
UNCOV
150
  let* modules, obj_dir =
×
151
    let first_exe = first_exe exes in
UNCOV
152
    Dir_contents.ocaml dir_contents
×
UNCOV
153
    >>= Ml_sources.modules_and_obj_dir ~libs:(Scope.libs scope) ~for_:(Exe { first_exe })
×
154
  in
UNCOV
155
  let* () = Check_rules.add_obj_dir sctx ~obj_dir (Ocaml Byte) in
×
UNCOV
156
  let ctx = Super_context.context sctx in
×
UNCOV
157
  let* ocaml = Context.ocaml ctx in
×
158
  let project = Scope.project scope in
×
159
  let explicit_js_mode = Dune_project.explicit_js_mode project in
×
UNCOV
160
  let js_of_ocaml = Js_of_ocaml.In_context.make ~dir exes.buildable.js_of_ocaml in
×
161
  let* linkages =
×
162
    let+ jsoo_enabled_modes =
163
      Jsoo_rules.jsoo_enabled_modes ~expander ~dir ~in_context:js_of_ocaml
UNCOV
164
    and+ jsoo_is_whole_program = Jsoo_rules.jsoo_is_whole_program sctx ~dir
×
165
    and+ dynamically_linked_foreign_archives =
UNCOV
166
      Context.dynamically_linked_foreign_archives ctx
×
167
    in
UNCOV
168
    linkages
×
169
      ocaml
170
      ~dynamically_linked_foreign_archives
171
      ~exes
172
      ~explicit_js_mode
173
      ~jsoo_enabled_modes
174
      ~jsoo_is_whole_program
175
  in
UNCOV
176
  let* flags = Buildable_rules.ocaml_flags sctx ~dir exes.buildable.flags in
×
177
  let* modules, pp =
×
178
    let+ modules, pp =
179
      Buildable_rules.modules_rules
×
180
        sctx
181
        (Executables (exes.buildable, Nonempty_list.to_list exes.names))
×
182
        expander
183
        ~dir
184
        scope
185
        modules
186
    in
UNCOV
187
    Modules.With_vlib.modules modules, pp
×
188
  in
UNCOV
189
  let programs = programs ~modules ~exes in
×
190
  let* cctx =
191
    let requires_compile = Lib.Compile.direct_requires compile_info in
UNCOV
192
    let requires_link = Lib.Compile.requires_link compile_info in
×
UNCOV
193
    let js_of_ocaml =
×
194
      Js_of_ocaml.Mode.Pair.mapi
195
        ~f:(fun mode x ->
UNCOV
196
          Option.some_if
×
197
            ((not explicit_js_mode) || List.exists linkages ~f:(Exe.Linkage.is_jsoo ~mode))
×
198
            x)
199
        js_of_ocaml
200
    in
201
    Compilation_context.create
×
202
      ()
203
      ~loc:exes.buildable.loc
204
      ~super_context:sctx
205
      ~scope
206
      ~obj_dir
207
      ~modules
208
      ~flags
209
      ~requires_link
210
      ~requires_compile
211
      ~preprocessing:pp
212
      ~js_of_ocaml
213
      ~opaque:Inherit_from_settings
214
      ~melange_package_name:None
215
      ~package:exes.package
216
  in
217
  let lib_config = ocaml.lib_config in
×
218
  let stdlib_dir = lib_config.stdlib_dir in
UNCOV
219
  let* requires_compile = Compilation_context.requires_compile cctx in
×
UNCOV
220
  let* requires_hidden = Compilation_context.requires_hidden cctx in
×
221
  let* dep_graphs =
×
222
    (* Building an archive for foreign stubs, we link the corresponding object
223
       files directly to improve perf. *)
224
    let link_deps, sandbox = Dep_conf_eval.unnamed ~expander exes.link_deps in
UNCOV
225
    let link_args =
×
226
      let use_standard_cxx_flags =
227
        match Dune_project.use_standard_c_and_cxx_flags project with
UNCOV
228
        | Some true -> Buildable.has_foreign_cxx exes.buildable
×
UNCOV
229
        | _ -> false
×
230
      in
231
      let open Action_builder.O in
232
      let link_flags =
233
        let* () = link_deps in
234
        let* link_flags =
×
UNCOV
235
          Action_builder.of_memo (Ocaml_flags_db.link_flags sctx ~dir exes.link_flags)
×
236
        in
237
        Link_flags.get ~use_standard_cxx_flags link_flags
×
238
      in
239
      let+ flags = link_flags
240
      and+ ctypes_cclib_flags =
241
        Ctypes_rules.ctypes_cclib_flags sctx ~expander ~buildable:exes.buildable
×
242
      in
243
      Command.Args.S
×
244
        [ As flags
245
        ; S
246
            (let ext_lib = lib_config.ext_lib in
247
             let foreign_archives = exes.buildable.foreign_archives |> List.map ~f:snd in
248
             (* XXX: don't these need the msvc hack being done in lib_rules? *)
249
             (* XXX: also the Command.quote_args being done in lib_rules? *)
UNCOV
250
             List.map foreign_archives ~f:(fun archive ->
×
UNCOV
251
               let lib =
×
252
                 Foreign.Archive.lib_file ~archive ~dir ~ext_lib ~mode:Mode.Select.All
253
               in
UNCOV
254
               Command.Args.S [ A "-cclib"; Dep (Path.build lib) ]))
×
255
          (* XXX: don't these need the msvc hack being done in lib_rules? *)
256
          (* XXX: also the Command.quote_args being done in lib_rules? *)
UNCOV
257
        ; As (List.concat_map ctypes_cclib_flags ~f:(fun f -> [ "-cclib"; f ]))
×
258
        ]
259
    in
260
    let* o_files =
UNCOV
261
      o_files sctx ~dir ~expander ~exes ~linkages ~dir_contents ~requires_compile
×
262
    in
263
    let* () = Check_rules.add_files sctx ~dir @@ Mode.Map.Multi.to_flat_list o_files in
×
264
    let buildable = exes.buildable in
×
265
    match buildable.ctypes with
UNCOV
266
    | None ->
×
267
      Exe.build_and_link_many
268
        cctx
269
        ~programs
270
        ~linkages
271
        ~link_args
272
        ~o_files
273
        ~promote:exes.promote
274
        ~embed_in_plugin_libraries
275
        ~sandbox
UNCOV
276
    | Some _ ->
×
277
      (* Ctypes stubgen builds utility .exe files that need to share modules
278
         with this compilation context. To support that, we extract the one-time
279
         run bits from [Exe.build_and_link_many] and run them here, then pass
280
         that to the [Exe.link_many] call here as well as the Ctypes_rules. This
281
         dance is done to avoid triggering duplicate rule exceptions. *)
282
      let+ () =
UNCOV
283
        let loc = fst (Nonempty_list.hd exes.names) in
×
UNCOV
284
        Ctypes_rules.gen_rules ~cctx ~buildable ~loc ~sctx ~scope ~dir
×
UNCOV
285
      and+ () = Module_compilation.build_all cctx
×
286
      and+ link =
UNCOV
287
        Exe.link_many
×
288
          ~programs
289
          ~linkages
290
          ~link_args
291
          ~o_files
292
          ~promote:exes.promote
293
          ~embed_in_plugin_libraries
294
          cctx
295
          ~sandbox
296
      in
UNCOV
297
      link
×
298
  in
299
  let+ () =
×
300
    Memo.parallel_iter dep_graphs.for_exes ~f:(Check_rules.add_cycle_check sctx ~dir)
×
301
  in
302
  ( cctx
×
303
  , Merlin.make
304
      ~requires_compile
305
      ~requires_hidden
306
      ~stdlib_dir
307
      ~flags
308
      ~modules
309
      ~libname:None
310
      ~obj_dir
311
      ~preprocess:
UNCOV
312
        (Preprocess.Per_module.without_instrumentation exes.buildable.preprocess)
×
UNCOV
313
      ~dialects:(Dune_project.dialects (Scope.project scope))
×
UNCOV
314
      ~ident:(Merlin_ident.for_exes ~names:(Nonempty_list.map ~f:snd exes.names))
×
315
      ~modes:`Exe )
316
;;
317

318
let compile_info ~scope (exes : Executables.t) =
319
  let dune_version = Scope.project scope |> Dune_project.dune_version in
×
320
  let+ pps =
×
321
    (* TODO resolution should be delayed *)
UNCOV
322
    Resolve.Memo.read_memo
×
UNCOV
323
      (Preprocess.Per_module.with_instrumentation
×
324
         exes.buildable.preprocess
UNCOV
325
         ~instrumentation_backend:(Lib.DB.instrumentation_backend (Scope.libs scope)))
×
UNCOV
326
    >>| Preprocess.Per_module.pps
×
327
  in
UNCOV
328
  Lib.DB.resolve_user_written_deps
×
UNCOV
329
    (Scope.libs scope)
×
330
    (`Exe exes.names)
331
    exes.buildable.libraries
332
    ~pps
333
    ~dune_version
334
    ~allow_overlaps:exes.buildable.allow_overlapping_dependencies
335
    ~forbidden_libraries:exes.forbidden_libraries
336
;;
337

338
let rules ~sctx ~dir ~dir_contents ~scope ~expander (exes : Executables.t) =
UNCOV
339
  let* compile_info = compile_info ~scope exes in
×
UNCOV
340
  let f () =
×
UNCOV
341
    executables_rules
×
342
      exes
343
      ~sctx
344
      ~dir
345
      ~dir_contents
346
      ~scope
347
      ~expander
348
      ~compile_info
349
      ~embed_in_plugin_libraries:exes.embed_in_plugin_libraries
350
  in
UNCOV
351
  let* () = Buildable_rules.gen_select_rules sctx compile_info ~dir
×
352
  and* () =
353
    let requires_link = Lib.Compile.requires_link compile_info in
UNCOV
354
    Bootstrap_info.gen_rules sctx exes ~dir ~requires_link
×
355
  in
UNCOV
356
  let merlin_ident = Merlin_ident.for_exes ~names:(Nonempty_list.map ~f:snd exes.names) in
×
UNCOV
357
  Buildable_rules.with_lib_deps (Super_context.context sctx) merlin_ident ~dir ~f
×
358
;;
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