File: import.ml

package info (click to toggle)
ocaml-dune 3.20.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 33,564 kB
  • sloc: ml: 175,178; asm: 28,570; ansic: 5,251; sh: 1,096; lisp: 625; makefile: 148; python: 125; cpp: 48; javascript: 10
file content (288 lines) | stat: -rw-r--r-- 9,059 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
include Stdune
include Dune_config_file
include Dune_vcs

include struct
  open Dune_engine
  module Build_config = Build_config
  module Build_system = Build_system
  module Build_system_error = Build_system_error
  module Load_rules = Load_rules
  module Hooks = Hooks
  module Action_builder = Dune_rules.Action_builder
  module Action = Action
  module Dep = Dep
  module Action_to_sh = Action_to_sh
  module Dpath = Dpath
  module Findlib = Dune_rules.Findlib
  module Diff_promotion = Diff_promotion
  module Targets = Targets
  module Context_name = Context_name
end

module Cached_digest = Dune_digest.Cached_digest

include struct
  open Source
  module Source_tree = Source_tree
  module Source_dir_status = Source_dir_status
  module Workspace = Workspace
end

include struct
  open Dune_rules
  module Super_context = Super_context
  module Context = Context
  module Dune_package = Dune_package
  module Resolve = Resolve
  module Dune_file = Dune_file
  module Library = Library
  module Melange = Melange
  module Melange_stanzas = Melange_stanzas
  module Executables = Executables
end

include struct
  open Cmdliner
  module Term = Term
  module Manpage = Manpage

  module Cmd = struct
    include Cmd

    let default_exits = List.map ~f:Exit_code.info Exit_code.all

    let info ?docs ?doc ?man ?envs ?version name =
      info ?docs ?doc ?man ?envs ?version ~exits:default_exits name
    ;;
  end
end

module Digest = Dune_digest
module Metrics = Dune_metrics
module Console = Dune_console

include struct
  open Dune_lang
  module Stanza = Stanza
  module Profile = Profile
  module Lib_name = Lib_name
  module Package_name = Package_name
  module Package = Package
  module Package_version = Package_version
  module Source_kind = Source_kind
  module Package_info = Package_info
  module Section = Section
  module Dune_project_name = Dune_project_name
  module Dune_project = Dune_project
end

module Log = Dune_util.Log
module Dune_rpc = Dune_rpc_private
module Graph = Dune_graph.Graph
include Common.Let_syntax

module Main : sig
  include module type of struct
    include Dune_rules.Main
  end

  val setup : unit -> build_system Memo.t Fiber.t
end = struct
  include Dune_rules.Main

  let setup () =
    let open Fiber.O in
    let* scheduler = Dune_engine.Scheduler.t () in
    Console.Status_line.set
      (Live
         (fun () ->
           match Fiber.Svar.read Build_system.state with
           | Initializing
           | Restarting_current_build
           | Build_succeeded__now_waiting_for_changes
           | Build_failed__now_waiting_for_changes -> Pp.nop
           | Building
               { Build_system.Progress.number_of_rules_executed = done_
               ; number_of_rules_discovered = total
               ; number_of_rules_failed = failed
               } ->
             Pp.verbatim
               (sprintf
                  "Done: %u%% (%u/%u, %u left%s) (jobs: %u)"
                  (if total = 0 then 0 else done_ * 100 / total)
                  done_
                  total
                  (total - done_)
                  (if failed = 0 then "" else sprintf ", %u failed" failed)
                  (Dune_engine.Scheduler.running_jobs_count scheduler))));
    Fiber.return (Memo.of_thunk get)
  ;;
end

module Scheduler = struct
  include Dune_engine.Scheduler

  let maybe_clear_screen ~details_hum (dune_config : Dune_config.t) =
    match Execution_env.inside_dune with
    | true -> (* Don't print anything here to make tests less verbose *) ()
    | false ->
      (match dune_config.terminal_persistence with
       | Clear_on_rebuild -> Console.reset ()
       | Clear_on_rebuild_and_flush_history -> Console.reset_flush_history ()
       | Preserve ->
         let message =
           sprintf
             "********** NEW BUILD (%s) **********"
             (String.concat ~sep:", " details_hum)
         in
         Console.print_user_message
           (User_message.make
              [ Pp.nop; Pp.tag User_message.Style.Success (Pp.verbatim message); Pp.nop ]))
  ;;

  let on_event dune_config _config = function
    | Run.Event.Tick -> Console.Status_line.refresh ()
    | Source_files_changed { details_hum } -> maybe_clear_screen ~details_hum dune_config
    | Build_interrupted ->
      Console.Status_line.set
        (Live
           (fun () ->
             let progression =
               match Fiber.Svar.read Build_system.state with
               | Initializing
               | Restarting_current_build
               | Build_succeeded__now_waiting_for_changes
               | Build_failed__now_waiting_for_changes -> Build_system.Progress.init
               | Building progress -> progress
             in
             Pp.seq
               (Pp.tag User_message.Style.Error (Pp.verbatim "Source files changed"))
               (Pp.verbatim
                  (sprintf
                     ", restarting current build... (%u/%u)"
                     progression.number_of_rules_executed
                     progression.number_of_rules_discovered))))
    | Build_finish build_result ->
      let message =
        match build_result with
        | Success -> Pp.tag User_message.Style.Success (Pp.verbatim "Success")
        | Failure ->
          let failure_message =
            match
              Build_system_error.(
                Id.Map.cardinal (Set.current (Fiber.Svar.read Build_system.errors)))
            with
            | 1 -> Pp.textf "Had 1 error"
            | n -> Pp.textf "Had %d errors" n
          in
          Pp.tag User_message.Style.Error failure_message
      in
      Console.Status_line.set
        (Constant (Pp.seq message (Pp.verbatim ", waiting for filesystem changes...")))
  ;;

  let rpc server =
    { Dune_engine.Rpc.run = Dune_rpc_impl.Server.run server
    ; stop = Dune_rpc_impl.Server.stop server
    ; ready = Dune_rpc_impl.Server.ready server
    }
  ;;

  let go_without_rpc_server ~(common : Common.t) ~config:dune_config f =
    let stats = Common.stats common in
    let config =
      let watch_exclusions = Common.watch_exclusions common in
      Dune_config.for_scheduler
        dune_config
        stats
        ~print_ctrl_c_warning:true
        ~watch_exclusions
    in
    Dune_rules.Clflags.concurrency := config.concurrency;
    Run.go config ~on_event:(on_event dune_config) f
  ;;

  let go_with_rpc_server ~common ~config f =
    let f =
      match Common.rpc common with
      | `Allow server -> fun () -> Dune_engine.Rpc.with_background_rpc (rpc server) f
      | `Forbid_builds -> f
    in
    go_without_rpc_server ~common ~config f
  ;;

  let go_with_rpc_server_and_console_status_reporting
        ~(common : Common.t)
        ~config:dune_config
        run
    =
    let server =
      match Common.rpc common with
      | `Allow server -> rpc server
      | `Forbid_builds -> Code_error.raise "rpc must be enabled in polling mode" []
    in
    let stats = Common.stats common in
    let config =
      let watch_exclusions = Common.watch_exclusions common in
      Dune_config.for_scheduler
        dune_config
        stats
        ~print_ctrl_c_warning:true
        ~watch_exclusions
    in
    Dune_rules.Clflags.concurrency := config.concurrency;
    let file_watcher = Common.file_watcher common in
    let run () =
      let open Fiber.O in
      Dune_engine.Rpc.with_background_rpc server
      @@ fun () ->
      let* () = Dune_engine.Rpc.ensure_ready () in
      run ()
    in
    Run.go config ~file_watcher ~on_event:(on_event dune_config) run
  ;;
end

let string_path_relative_to_specified_root (root : Workspace_root.t) path =
  if Filename.is_relative path then Filename.concat root.dir path else path
;;

let restore_cwd_and_execve root prog args env =
  let prog = string_path_relative_to_specified_root root prog in
  Proc.restore_cwd_and_execve prog args ~env
;;

(* Adapted from
   https://github.com/ocaml/opam/blob/fbbe93c3f67034da62d28c8666ec6b05e0a9b17c/src/client/opamArg.ml#L759 *)
let command_alias ?orig_name cmd term name =
  let orig =
    match orig_name with
    | Some s -> s
    | None -> Cmd.name cmd
  in
  let doc = Printf.sprintf "An alias for $(b,%s)." orig in
  let man =
    [ `S "DESCRIPTION"
    ; `P (Printf.sprintf "$(mname)$(b, %s) is an alias for $(mname)$(b, %s)." name orig)
    ; `P (Printf.sprintf "See $(mname)$(b, %s --help) for details." orig)
    ; `Blocks Common.help_secs
    ]
  in
  Cmd.v (Cmd.info name ~docs:"COMMAND ALIASES" ~doc ~man) term
;;

(* The build system has some global state which makes it unsafe for
   multiple instances of it to be executed concurrently, so we ensure
   serialization by holding this mutex while running the build system. *)
let build_system_mutex = Fiber.Mutex.create ()

let build f =
  Hooks.End_of_build.once Promote.Diff_promotion.finalize;
  Fiber.Mutex.with_lock build_system_mutex ~f:(fun () -> Build_system.run f)
;;

let build_exn f =
  Hooks.End_of_build.once Promote.Diff_promotion.finalize;
  Fiber.Mutex.with_lock build_system_mutex ~f:(fun () -> Build_system.run_exn f)
;;