Skip to content

Commit 3a8e777

Browse files
OlivierNicoleEnoumy
authored andcommitted
Add flag --empty-sourcemap
This patch implements the `--empty-sourcemap` flag. It is used to generate an empty sourcemap, which is cheap. Sometimes application authors would like the cheapness of not building sourcemap files to speed up development iterations, but their build pipelines do not handle the case where `.map` files are not produced at all (think, e.g., custom Dune rules depending on `.bc.map` files). In that cases, they would like to still generate the empty `.bc.map` files. Co-authored-by: enoumy <enoumy@gmail.com>
1 parent 8065482 commit 3a8e777

File tree

9 files changed

+114
-54
lines changed

9 files changed

+114
-54
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* Ppx: explicitly disallow polymorphic method (#1897)
2424
* Ppx: allow "function" in object literals (#1897)
2525
* Lib: make the Wasm version of Json.output work with native ints and JavaScript objects (#1872)
26+
* Compiler: add the `--empty-sourcemap` flag
2627
* Compiler: static evaluation of more primitives (#1912)
2728
* Compiler: faster compilation by stopping sooner when optimizations become unproductive (#1939)
2829
* Compiler: improve debug/sourcemap location of closures (#1947)

compiler/bin-js_of_ocaml/cmd_arg.ml

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ type t =
5454
{ common : Jsoo_cmdline.Arg.t
5555
; (* compile option *)
5656
profile : Driver.profile option
57-
; source_map : (string option * Source_map.Standard.t) option
57+
; source_map : Source_map.Encoding_spec.t option
5858
; runtime_files : string list
5959
; no_runtime : bool
6060
; include_runtime : bool
@@ -158,6 +158,10 @@ let options =
158158
let doc = "Do not inline sources in source map." in
159159
Arg.(value & flag & info [ "source-map-no-source" ] ~doc)
160160
in
161+
let sourcemap_empty =
162+
let doc = "Always generate empty source maps." in
163+
Arg.(value & flag & info [ "empty-sourcemap"; "empty-source-map" ] ~doc)
164+
in
161165
let sourcemap_root =
162166
let doc = "root dir for source map." in
163167
Arg.(value & opt (some string) None & info [ "source-map-root" ] ~doc)
@@ -296,6 +300,7 @@ let options =
296300
sourcemap
297301
sourcemap_inline_in_js
298302
sourcemap_don't_inline_content
303+
sourcemap_empty
299304
sourcemap_root
300305
target_env
301306
output_file
@@ -330,12 +335,19 @@ let options =
330335
| `Name file, _ -> Some file, Some (chop_extension file ^ ".map")
331336
| `Stdout, _ -> None, None
332337
in
333-
Some
334-
( sm_output_file
335-
, { (Source_map.Standard.empty ~inline_source_content) with
336-
file
337-
; sourceroot = sourcemap_root
338-
} )
338+
let source_map =
339+
{ (Source_map.Standard.empty ~inline_source_content) with
340+
file
341+
; sourceroot = sourcemap_root
342+
}
343+
in
344+
let spec =
345+
{ Source_map.Encoding_spec.output_file = sm_output_file
346+
; source_map
347+
; keep_empty = sourcemap_empty
348+
}
349+
in
350+
Some spec
339351
else None
340352
in
341353
let params : (string * string) list = List.flatten set_param in
@@ -391,6 +403,7 @@ let options =
391403
$ sourcemap
392404
$ sourcemap_inline_in_js
393405
$ sourcemap_don't_inline_content
406+
$ sourcemap_empty
394407
$ sourcemap_root
395408
$ target_env
396409
$ output_file
@@ -437,6 +450,10 @@ let options_runtime_only =
437450
let doc = "Do not inline sources in source map." in
438451
Arg.(value & flag & info [ "source-map-no-source" ] ~doc)
439452
in
453+
let sourcemap_empty =
454+
let doc = "Always generate empty source maps." in
455+
Arg.(value & flag & info [ "empty-sourcemap"; "empty-source-map" ] ~doc)
456+
in
440457
let sourcemap_root =
441458
let doc = "root dir for source map." in
442459
Arg.(value & opt (some string) None & info [ "source-map-root" ] ~doc)
@@ -548,6 +565,7 @@ let options_runtime_only =
548565
sourcemap
549566
sourcemap_inline_in_js
550567
sourcemap_don't_inline_content
568+
sourcemap_empty
551569
sourcemap_root
552570
target_env
553571
output_file
@@ -570,12 +588,19 @@ let options_runtime_only =
570588
| `Name file, _ -> Some file, Some (chop_extension file ^ ".map")
571589
| `Stdout, _ -> None, None
572590
in
573-
Some
574-
( sm_output_file
575-
, { (Source_map.Standard.empty ~inline_source_content) with
576-
file
577-
; sourceroot = sourcemap_root
578-
} )
591+
let source_map =
592+
{ (Source_map.Standard.empty ~inline_source_content) with
593+
file
594+
; sourceroot = sourcemap_root
595+
}
596+
in
597+
let spec =
598+
{ Source_map.Encoding_spec.output_file = sm_output_file
599+
; source_map
600+
; keep_empty = sourcemap_empty
601+
}
602+
in
603+
Some spec
579604
else None
580605
in
581606
let params : (string * string) list = List.flatten set_param in
@@ -626,6 +651,7 @@ let options_runtime_only =
626651
$ sourcemap
627652
$ sourcemap_inline_in_js
628653
$ sourcemap_don't_inline_content
654+
$ sourcemap_empty
629655
$ sourcemap_root
630656
$ target_env
631657
$ output_file

compiler/bin-js_of_ocaml/cmd_arg.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type t =
2323
{ common : Jsoo_cmdline.Arg.t
2424
; (* compile option *)
2525
profile : Driver.profile option
26-
; source_map : (string option * Source_map.Standard.t) option
26+
; source_map : Source_map.Encoding_spec.t option
2727
; runtime_files : string list
2828
; no_runtime : bool
2929
; include_runtime : bool

compiler/bin-js_of_ocaml/compile.ml

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,33 +37,33 @@ let jsoo_header formatter build_info =
3737
Pretty_print.string formatter (Printf.sprintf "%s\n" Global_constant.header);
3838
Pretty_print.string formatter (Build_info.to_string build_info)
3939

40-
type source_map_output =
41-
| No_sourcemap
42-
| Inline
43-
| File of string
40+
let source_map_enabled : Source_map.Encoding_spec.t option -> bool = function
41+
| None -> false
42+
| Some _ -> true
4443

45-
let source_map_enabled = function
46-
| No_sourcemap -> false
47-
| Inline | File _ -> true
48-
49-
let output_gen ~standalone ~custom_header ~build_info ~source_map output_file f =
44+
let output_gen
45+
~standalone
46+
~custom_header
47+
~build_info
48+
~(source_map : Source_map.Encoding_spec.t option)
49+
output_file
50+
f =
5051
let f chan k =
5152
let fmt = Pretty_print.to_out_channel chan in
5253
Driver.configure fmt;
5354
if standalone then header ~custom_header fmt;
5455
if Config.Flag.header () then jsoo_header fmt build_info;
5556
let sm = f ~standalone ~source_map (k, fmt) in
5657
match source_map, sm with
57-
| No_sourcemap, _ | _, None -> ()
58-
| ((Inline | File _) as output), Some sm ->
58+
| None, _ | _, None -> ()
59+
| Some { output_file = output; source_map = _; keep_empty = _ }, Some sm ->
5960
if Debug.find "invariant" () then Source_map.invariant sm;
6061
let urlData =
6162
match output with
62-
| No_sourcemap -> assert false
63-
| Inline ->
63+
| None ->
6464
let data = Source_map.to_string sm in
6565
"data:application/json;base64," ^ Base64.encode_exn data
66-
| File output_file ->
66+
| Some output_file ->
6767
Source_map.to_file sm output_file;
6868
Filename.basename output_file
6969
in
@@ -156,12 +156,8 @@ let run
156156
; include_runtime
157157
; effects
158158
} =
159-
let source_map_base = Option.map ~f:snd source_map in
160-
let source_map =
161-
match source_map with
162-
| None -> No_sourcemap
163-
| Some (None, _) -> Inline
164-
| Some (Some file, _) -> File file
159+
let source_map_base =
160+
Option.map ~f:(fun spec -> spec.Source_map.Encoding_spec.source_map) source_map
165161
in
166162
let include_cmis = toplevel && not no_cmis in
167163
let custom_header = common.Jsoo_cmdline.Arg.custom_header in
@@ -223,9 +219,9 @@ let run
223219
Linker.check_deps ();
224220
if times () then Format.eprintf " parsing js: %a@." Timer.print t1;
225221
if times () then Format.eprintf "Start parsing...@.";
226-
let need_debug = source_map_enabled source_map || Config.Flag.debuginfo () in
222+
let need_debug = Option.is_some source_map || Config.Flag.debuginfo () in
227223
let check_debug (one : Parse_bytecode.one) =
228-
if source_map_enabled source_map && Parse_bytecode.Debug.is_empty one.debug
224+
if Option.is_some source_map && Parse_bytecode.Debug.is_empty one.debug
229225
then
230226
warn
231227
"Warning: '--source-map' is enabled but the bytecode program was compiled with \
@@ -254,7 +250,7 @@ let run
254250
(one : Parse_bytecode.one)
255251
~check_sourcemap
256252
~standalone
257-
~source_map
253+
~(source_map : Source_map.Encoding_spec.t option)
258254
~link
259255
output_file =
260256
if check_sourcemap then check_debug one;

compiler/bin-js_of_ocaml/link.ml

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ open Cmdliner
2323

2424
type t =
2525
{ common : Jsoo_cmdline.Arg.t
26-
; source_map : (string option * Source_map.Standard.t) option
26+
; source_map : Source_map.Encoding_spec.t option
2727
; js_files : string list
2828
; output_file : string option
2929
; resolve_sourcemap_url : bool
@@ -51,6 +51,10 @@ let options =
5151
let doc = "Inline sourcemap in the generated JavaScript." in
5252
Arg.(value & flag & info [ "source-map-inline" ] ~doc)
5353
in
54+
let sourcemap_empty =
55+
let doc = "Always generate empty source maps." in
56+
Arg.(value & flag & info [ "empty-sourcemap"; "empty-source-map" ] ~doc)
57+
in
5458
let sourcemap_root =
5559
let doc = "root dir for source map." in
5660
Arg.(value & opt (some string) None & info [ "source-map-root" ] ~doc)
@@ -83,6 +87,7 @@ let options =
8387
no_sourcemap
8488
sourcemap
8589
sourcemap_inline_in_js
90+
sourcemap_empty
8691
sourcemap_root
8792
output_file
8893
resolve_sourcemap_url
@@ -100,12 +105,19 @@ let options =
100105
| Some file -> Some file, Some (chop_extension file ^ ".map")
101106
| None -> None, None
102107
in
103-
Some
104-
( sm_output_file
105-
, { (Source_map.Standard.empty ~inline_source_content:true) with
106-
file
107-
; sourceroot = sourcemap_root
108-
} )
108+
let source_map =
109+
{ (Source_map.Standard.empty ~inline_source_content:true) with
110+
file
111+
; sourceroot = sourcemap_root
112+
}
113+
in
114+
let spec =
115+
{ Source_map.Encoding_spec.output_file = sm_output_file
116+
; source_map
117+
; keep_empty = sourcemap_empty
118+
}
119+
in
120+
Some spec
109121
else None
110122
in
111123
`Ok
@@ -126,6 +138,7 @@ let options =
126138
$ no_sourcemap
127139
$ sourcemap
128140
$ sourcemap_inline_in_js
141+
$ sourcemap_empty
129142
$ sourcemap_root
130143
$ output_file
131144
$ resolve_sourcemap_url

compiler/lib/link_js.ml

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,14 @@ end = struct
224224
build_info, units
225225
end
226226

227-
let link ~output ~linkall ~mklib ~toplevel ~files ~resolve_sourcemap_url ~source_map =
227+
let link
228+
~output
229+
~linkall
230+
~mklib
231+
~toplevel
232+
~files
233+
~resolve_sourcemap_url
234+
~(source_map : Source_map.Encoding_spec.t option) =
228235
(* we currently don't do anything with [toplevel]. It could be used
229236
to conditionally include link_info ?*)
230237
ignore (toplevel : bool);
@@ -315,13 +322,12 @@ let link ~output ~linkall ~mklib ~toplevel ~files ~resolve_sourcemap_url ~source
315322
match Line_reader.peek ic with
316323
| None -> ()
317324
| Some line ->
318-
(match
319-
action
320-
~resolve_sourcemap_url
321-
~drop_source_map:(Option.is_none source_map)
322-
file
323-
line
324-
with
325+
let drop_source_map =
326+
match source_map with
327+
| None | Some { keep_empty = true; _ } -> true
328+
| Some { keep_empty = false; _ } -> false
329+
in
330+
(match action ~resolve_sourcemap_url ~drop_source_map file line with
325331
| Keep -> copy ic oc
326332
| Build_info bi ->
327333
skip ic;
@@ -437,7 +443,7 @@ let link ~output ~linkall ~mklib ~toplevel ~files ~resolve_sourcemap_url ~source
437443
let t = Timer.make () in
438444
match source_map with
439445
| None -> ()
440-
| Some (file, init_sm) ->
446+
| Some { output_file = file; source_map = init_sm; keep_empty = _ } ->
441447
let sections =
442448
List.rev_map !sm ~f:(fun (sm, reloc, _offset) ->
443449
let sm =

compiler/lib/link_js.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ val link :
2424
-> toplevel:bool
2525
-> files:string list
2626
-> resolve_sourcemap_url:bool
27-
-> source_map:(string option * Source_map.Standard.t) option
27+
-> source_map:Source_map.Encoding_spec.t option
2828
-> unit

compiler/lib/source_map.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,3 +792,12 @@ let find_in_js_file file =
792792
in
793793
Some (of_string content)
794794
| _ -> None
795+
796+
module Encoding_spec = struct
797+
type t =
798+
{ output_file : string option (** Source map file ([None] means generate inline. *)
799+
; source_map : Standard.t (** Source map to extend. *)
800+
; keep_empty : bool
801+
(** Don't add anything to the source map (for js_of_ocaml's "empty sourcemap" option. *)
802+
}
803+
end

compiler/lib/source_map.mli

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,12 @@ type info =
156156
; sources : string list
157157
; names : string list
158158
}
159+
160+
module Encoding_spec : sig
161+
type t =
162+
{ output_file : string option (** Source map file ([None] means generate inline. *)
163+
; source_map : Standard.t (** Source map to extend. *)
164+
; keep_empty : bool
165+
(** Don't add anything to the source map (for js_of_ocaml's "empty sourcemap" option. *)
166+
}
167+
end

0 commit comments

Comments
 (0)