Skip to content

Commit 94f43ef

Browse files
committed
Compiler: allow to link cmo.js into a cma.js
This is useful to achieve better incrementatlity during sepearate compilation.
1 parent fa1ae1e commit 94f43ef

File tree

6 files changed

+66
-13
lines changed

6 files changed

+66
-13
lines changed

compiler/bin-js_of_ocaml/link.ml

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type t =
2828
; output_file : string option
2929
; resolve_sourcemap_url : bool
3030
; linkall : bool
31+
; mklib : bool
3132
}
3233

3334
let options =
@@ -65,6 +66,14 @@ let options =
6566
let doc = "Link all compilation units." in
6667
Arg.(value & flag & info [ "linkall" ] ~doc)
6768
in
69+
let mklib =
70+
let doc = "similar to -a" in
71+
Arg.(value & flag & info [ "a" ] ~doc)
72+
in
73+
let toplevel =
74+
let doc = "toplevel" in
75+
Arg.(value & flag & info [ "toplevel" ] ~doc)
76+
in
6877
let build_t
6978
common
7079
no_sourcemap
@@ -74,7 +83,9 @@ let options =
7483
output_file
7584
resolve_sourcemap_url
7685
js_files
77-
linkall =
86+
linkall
87+
mklib
88+
_toplevel =
7889
let chop_extension s = try Filename.chop_extension s with Invalid_argument _ -> s in
7990
let source_map =
8091
if (not no_sourcemap) && (sourcemap || sourcemap_inline_in_js)
@@ -97,7 +108,8 @@ let options =
97108
} )
98109
else None
99110
in
100-
`Ok { common; output_file; js_files; source_map; resolve_sourcemap_url; linkall }
111+
`Ok
112+
{ common; output_file; js_files; source_map; resolve_sourcemap_url; linkall; mklib }
101113
in
102114
let t =
103115
Term.(
@@ -110,19 +122,28 @@ let options =
110122
$ output_file
111123
$ resolve_sourcemap_url
112124
$ js_files
113-
$ linkall)
125+
$ linkall
126+
$ mklib
127+
$ toplevel)
114128
in
115129
Term.ret t
116130

117-
let f { common; output_file; source_map; resolve_sourcemap_url; js_files; linkall } =
131+
let f { common; output_file; source_map; resolve_sourcemap_url; js_files; linkall; mklib }
132+
=
118133
Jsoo_cmdline.Arg.eval common;
119134
let with_output f =
120135
match output_file with
121136
| None -> f stdout
122137
| Some file -> Filename.gen_file file f
123138
in
124139
with_output (fun output ->
125-
Link_js.link ~output ~linkall ~files:js_files ~source_map ~resolve_sourcemap_url)
140+
Link_js.link
141+
~output
142+
~linkall
143+
~mklib
144+
~files:js_files
145+
~source_map
146+
~resolve_sourcemap_url)
126147

127148
let info =
128149
Info.make

compiler/lib/build_info.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ let create kind =
6161
]
6262
|> List.fold_left ~init:StringMap.empty ~f:(fun acc (k, v) -> StringMap.add k v acc)
6363

64+
let with_kind t kind = StringMap.add "kind" (string_of_kind kind) t
65+
6466
let prefix = "//# buildInfo:"
6567

6668
let to_string info =

compiler/lib/build_info.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ val to_string : t -> string
3434

3535
val parse : string -> t option
3636

37+
val with_kind : t -> kind -> t
38+
3739
exception
3840
Incompatible_build_info of
3941
{ key : string

compiler/lib/link_js.ml

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ module Line_writer : sig
101101

102102
val write : ?source:Line_reader.t -> t -> string -> unit
103103

104+
val write_lines : ?source:Line_reader.t -> t -> string -> unit
105+
104106
val lnum : t -> int
105107
end = struct
106108
type t =
@@ -134,6 +136,16 @@ end = struct
134136
t.source <- source;
135137
t.lnum <- t.lnum + lnum_off
136138

139+
let write_lines ?source t lines =
140+
let l = String.split_on_char ~sep:'\n' lines in
141+
let rec w = function
142+
| [ "" ] | [] -> ()
143+
| s :: xs ->
144+
write ?source t s;
145+
w xs
146+
in
147+
w l
148+
137149
let lnum t = t.lnum
138150
end
139151

@@ -231,7 +243,7 @@ end = struct
231243
build_info, units
232244
end
233245

234-
let link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map =
246+
let link ~output ~linkall ~mklib ~files ~resolve_sourcemap_url ~source_map =
235247
let t = Timer.make () in
236248
let oc = Line_writer.of_channel output in
237249
let warn_effects = ref false in
@@ -255,6 +267,7 @@ let link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map =
255267
~f:(fun (info : Unit_info.t) (requires, to_link, all) ->
256268
let all = StringSet.union all info.provides in
257269
if (not (Config.Flag.auto_link ()))
270+
|| mklib
258271
|| cmo_file
259272
|| linkall
260273
|| info.force_link
@@ -266,7 +279,7 @@ let link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map =
266279
else requires, to_link, all))
267280
in
268281
let skip = StringSet.diff all to_link in
269-
if not (StringSet.is_empty missing)
282+
if (not (StringSet.is_empty missing)) && not mklib
270283
then
271284
failwith
272285
(Printf.sprintf
@@ -290,6 +303,8 @@ let link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map =
290303
: int);
291304
sym_js := s :: !sym_js)
292305
u.Unit_info.provides));
306+
307+
let build_info_emitted = ref false in
293308
List.iter files ~f:(fun (file, (build_info_for_file, units)) ->
294309
let sm_for_file = ref None in
295310
let ic = Line_reader.open_ file in
@@ -311,7 +326,14 @@ let link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map =
311326
file
312327
line
313328
with
314-
| Keep | Build_info _ -> copy ic oc
329+
| Keep -> copy ic oc
330+
| Build_info bi ->
331+
skip ic;
332+
if not !build_info_emitted
333+
then (
334+
let bi = if mklib then Build_info.with_kind bi `Cma else bi in
335+
Line_writer.write_lines oc (Build_info.to_string bi);
336+
build_info_emitted := true)
315337
| Drop -> skip ic
316338
| Unit ->
317339
let u = Units.read ic Unit_info.empty in
@@ -327,7 +349,11 @@ let link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map =
327349
then
328350
Format.eprintf
329351
"Copy %s@."
330-
(String.concat ~sep:"," (StringSet.elements u.provides)))
352+
(String.concat ~sep:"," (StringSet.elements u.provides));
353+
if mklib
354+
then
355+
let u = if linkall then { u with force_link = true } else u in
356+
Line_writer.write_lines oc (Unit_info.to_string u))
331357
else (
332358
if debug ()
333359
then
@@ -345,7 +371,7 @@ let link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map =
345371
skip ic
346372
done)
347373
| Source_map x ->
348-
Line_reader.drop ic;
374+
skip ic;
349375
sm_for_file := Some x);
350376
read ()
351377
in
@@ -378,7 +404,7 @@ let link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map =
378404
(Parse_bytecode.Debug.create ~include_cmis:false false)
379405
code;
380406
let content = Buffer.contents b in
381-
String.split_on_char ~sep:'\n' content |> List.iter ~f:(Line_writer.write oc));
407+
Line_writer.write_lines oc content);
382408
(match !sm_for_file with
383409
| None -> ()
384410
| Some x -> sm := (x, !reloc) :: !sm);
@@ -422,8 +448,8 @@ let link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map =
422448
Line_writer.write oc s));
423449
if times () then Format.eprintf " sourcemap: %a@." Timer.print t
424450

425-
let link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map =
426-
try link ~output ~linkall ~files ~resolve_sourcemap_url ~source_map
451+
let link ~output ~linkall ~mklib ~files ~resolve_sourcemap_url ~source_map =
452+
try link ~output ~linkall ~mklib ~files ~resolve_sourcemap_url ~source_map
427453
with Build_info.Incompatible_build_info { key; first = f1, v1; second = f2, v2 } ->
428454
let string_of_v = function
429455
| None -> "<empty>"

compiler/lib/link_js.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
val link :
2121
output:out_channel
2222
-> linkall:bool
23+
-> mklib:bool
2324
-> files:string list
2425
-> resolve_sourcemap_url:bool
2526
-> source_map:(string option * Source_map.t) option

compiler/tests-sourcemap/dump.reference

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ b.ml:1:10 -> 17: function f(x){<>return x - 1 | 0;}
55
b.ml:1:6 -> 24: function f(x){return <>x - 1 | 0;}
66
b.ml:1:15 -> 34: function f(x){return x - 1 | 0;<>}
77
b.ml:1:4 -> 23: var Testlib_B = [0, <>f];
8+
d.ml:-1:-1 -> 2: <>}
89
a.ml:-1:-1 -> 3: <>function caml_call1(f, a0){
910
a.ml:-1:-1 -> 2: <>}

0 commit comments

Comments
 (0)