Skip to content

Commit 4efc86c

Browse files
authored
Runtime: allow dynlink of precompiled js with separate compilation (#1676)
1 parent 693fa62 commit 4efc86c

File tree

8 files changed

+110
-6
lines changed

8 files changed

+110
-6
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* Runtime: change Sys.os_type on windows (Cygwin -> Win32)
1515
* Runtime: backtraces are really expensive, they need to be be explicitly
1616
requested at compile time (--enable with-js-error) or at startup (OCAMLRUNPARAM=b=1)
17+
* Runtime: allow dynlink of precompiled js with separate compilation (#1676)
1718
* Lib: Modify Typed_array API for compatibility with WebAssembly
1819

1920

compiler/tests-dynlink-js/dune

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,48 @@
22
(name main)
33
(modules main)
44
(libraries js_of_ocaml)
5-
(modes byte))
5+
(link_flags
6+
(:standard -linkall))
7+
;; Until dune is fixed https://github.com/ocaml/dune/pull/10935
8+
(js_of_ocaml
9+
(flags
10+
(:standard)
11+
--linkall
12+
(:include effects_flags.sexp))
13+
(build_runtime_flags
14+
(:standard)
15+
(:include effects_flags.sexp))
16+
(link_flags (:standard)))
17+
(modes js byte))
18+
19+
(executable
20+
(name effects_flags)
21+
(modules effects_flags))
22+
23+
(rule
24+
(target effects_flags.sexp)
25+
(action
26+
(with-stdout-to
27+
%{target}
28+
(run ./effects_flags.exe sexp %{profile}))))
29+
30+
(rule
31+
(target effects_flags.txt)
32+
(action
33+
(with-stdout-to
34+
%{target}
35+
(run ./effects_flags.exe txt %{profile}))))
636

737
(rule
838
(target main.js)
939
(action
10-
(run %{bin:js_of_ocaml} --linkall -o %{target} %{dep:main.bc})))
40+
(run
41+
%{bin:js_of_ocaml}
42+
--linkall
43+
%{read-strings:effects_flags.txt}
44+
-o
45+
%{target}
46+
%{dep:main.bc})))
1147

1248
(rule
1349
(target plugin.cmo)
@@ -17,17 +53,52 @@
1753
(rule
1854
(target plugin.js)
1955
(action
20-
(run %{bin:js_of_ocaml} %{dep:./plugin.cmo})))
56+
(run
57+
%{bin:js_of_ocaml}
58+
%{read-strings:effects_flags.txt}
59+
%{dep:./plugin.cmo})))
60+
61+
(rule
62+
(target plugin2.cma)
63+
(action
64+
(run
65+
%{bin:ocamlc}
66+
-a
67+
%{dep:./plugin2a.ml}
68+
%{dep:./plugin2b.ml}
69+
-o
70+
plugin2.cma)))
71+
72+
(rule
73+
(target plugin2.js)
74+
(action
75+
(run
76+
%{bin:js_of_ocaml}
77+
%{read-strings:effects_flags.txt}
78+
%{dep:./plugin2.cma})))
2179

2280
(rule
2381
(target main.out)
24-
(deps plugin.js)
82+
(deps plugin.js plugin2.js)
2583
(action
2684
(with-outputs-to
2785
%{target}
2886
(run %{bin:node} %{dep:./main.js}))))
2987

88+
(rule
89+
(target main.out2)
90+
(deps plugin.js plugin2.js)
91+
(action
92+
(with-outputs-to
93+
%{target}
94+
(run %{bin:node} %{dep:./main.bc.js}))))
95+
3096
(rule
3197
(alias runtest)
3298
(action
3399
(diff main.out.expected main.out)))
100+
101+
(rule
102+
(alias runtest)
103+
(action
104+
(diff main.out.expected main.out2)))
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
let enable b n =
2+
let f = if b then "--enable" else "--disable" in
3+
[ f; n ]
4+
5+
let () =
6+
let major = String.split_on_char '.' Sys.ocaml_version |> List.hd |> int_of_string in
7+
let has_effect l =
8+
match l with
9+
| [ "using-effects" ] -> major >= 5
10+
| _ -> false
11+
in
12+
let aux l = enable (has_effect l) "effects" in
13+
match Sys.argv |> Array.to_list |> List.tl with
14+
| "txt" :: rest -> List.iter print_endline (aux rest)
15+
| "sexp" :: rest ->
16+
print_endline "(";
17+
List.iter print_endline (aux rest);
18+
print_endline ")"
19+
| _ -> assert false

compiler/tests-dynlink-js/main.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ let require s =
55
Js.Unsafe.fun_call (Js.Unsafe.js_expr "require") [| Js.Unsafe.inject (Js.string s) |]
66

77
let () = require "./plugin.js"
8+
9+
let () = require "./plugin2.js"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
hello
22
plugin loaded
3+
plugin 2a loaded
4+
plugin 2b loaded

compiler/tests-dynlink-js/plugin2a.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let () = print_endline "plugin 2a loaded"

compiler/tests-dynlink-js/plugin2b.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let () = print_endline "plugin 2b loaded"

runtime/stdlib.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,15 @@ var caml_global_data = [0];
150150
//Requires: caml_jsstring_of_string
151151
function caml_build_symbols(symb) {
152152
var r = {};
153+
var max = -1;
153154
if (symb) {
154155
for (var i = 1; i < symb.length; i++) {
155-
r[caml_jsstring_of_string(symb[i][1])] = symb[i][2];
156+
var idx = symb[i][2];
157+
max = Math.max(max, idx);
158+
r[caml_jsstring_of_string(symb[i][1])] = idx;
156159
}
157160
}
161+
r.next_idx = max + 1;
158162
return r;
159163
}
160164

@@ -173,7 +177,10 @@ function caml_register_global(n, v, name_opt) {
173177
var nid = caml_global_data.symidx[name];
174178
if (nid >= 0) n = nid;
175179
else {
176-
caml_failwith("caml_register_global: cannot locate " + name);
180+
// The unit is unknown, this can happen when dynlinking a precompiled js,
181+
// let's allocate a fresh idx.
182+
var n = caml_global_data.symidx.next_idx++;
183+
caml_global_data.symidx[name] = n;
177184
}
178185
}
179186
}

0 commit comments

Comments
 (0)