Skip to content

Commit

Permalink
Runtime: allow dynlink of precompiled js with separate compilation (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
hhugo authored Sep 19, 2024
1 parent 693fa62 commit 4efc86c
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Runtime: change Sys.os_type on windows (Cygwin -> Win32)
* Runtime: backtraces are really expensive, they need to be be explicitly
requested at compile time (--enable with-js-error) or at startup (OCAMLRUNPARAM=b=1)
* Runtime: allow dynlink of precompiled js with separate compilation (#1676)
* Lib: Modify Typed_array API for compatibility with WebAssembly


Expand Down
79 changes: 75 additions & 4 deletions compiler/tests-dynlink-js/dune
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,48 @@
(name main)
(modules main)
(libraries js_of_ocaml)
(modes byte))
(link_flags
(:standard -linkall))
;; Until dune is fixed https://github.com/ocaml/dune/pull/10935
(js_of_ocaml
(flags
(:standard)
--linkall
(:include effects_flags.sexp))
(build_runtime_flags
(:standard)
(:include effects_flags.sexp))
(link_flags (:standard)))
(modes js byte))

(executable
(name effects_flags)
(modules effects_flags))

(rule
(target effects_flags.sexp)
(action
(with-stdout-to
%{target}
(run ./effects_flags.exe sexp %{profile}))))

(rule
(target effects_flags.txt)
(action
(with-stdout-to
%{target}
(run ./effects_flags.exe txt %{profile}))))

(rule
(target main.js)
(action
(run %{bin:js_of_ocaml} --linkall -o %{target} %{dep:main.bc})))
(run
%{bin:js_of_ocaml}
--linkall
%{read-strings:effects_flags.txt}
-o
%{target}
%{dep:main.bc})))

(rule
(target plugin.cmo)
Expand All @@ -17,17 +53,52 @@
(rule
(target plugin.js)
(action
(run %{bin:js_of_ocaml} %{dep:./plugin.cmo})))
(run
%{bin:js_of_ocaml}
%{read-strings:effects_flags.txt}
%{dep:./plugin.cmo})))

(rule
(target plugin2.cma)
(action
(run
%{bin:ocamlc}
-a
%{dep:./plugin2a.ml}
%{dep:./plugin2b.ml}
-o
plugin2.cma)))

(rule
(target plugin2.js)
(action
(run
%{bin:js_of_ocaml}
%{read-strings:effects_flags.txt}
%{dep:./plugin2.cma})))

(rule
(target main.out)
(deps plugin.js)
(deps plugin.js plugin2.js)
(action
(with-outputs-to
%{target}
(run %{bin:node} %{dep:./main.js}))))

(rule
(target main.out2)
(deps plugin.js plugin2.js)
(action
(with-outputs-to
%{target}
(run %{bin:node} %{dep:./main.bc.js}))))

(rule
(alias runtest)
(action
(diff main.out.expected main.out)))

(rule
(alias runtest)
(action
(diff main.out.expected main.out2)))
19 changes: 19 additions & 0 deletions compiler/tests-dynlink-js/effects_flags.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
let enable b n =
let f = if b then "--enable" else "--disable" in
[ f; n ]

let () =
let major = String.split_on_char '.' Sys.ocaml_version |> List.hd |> int_of_string in
let has_effect l =
match l with
| [ "using-effects" ] -> major >= 5
| _ -> false
in
let aux l = enable (has_effect l) "effects" in
match Sys.argv |> Array.to_list |> List.tl with
| "txt" :: rest -> List.iter print_endline (aux rest)
| "sexp" :: rest ->
print_endline "(";
List.iter print_endline (aux rest);
print_endline ")"
| _ -> assert false
2 changes: 2 additions & 0 deletions compiler/tests-dynlink-js/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ let require s =
Js.Unsafe.fun_call (Js.Unsafe.js_expr "require") [| Js.Unsafe.inject (Js.string s) |]

let () = require "./plugin.js"

let () = require "./plugin2.js"
2 changes: 2 additions & 0 deletions compiler/tests-dynlink-js/main.out.expected
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
hello
plugin loaded
plugin 2a loaded
plugin 2b loaded
1 change: 1 addition & 0 deletions compiler/tests-dynlink-js/plugin2a.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
let () = print_endline "plugin 2a loaded"
1 change: 1 addition & 0 deletions compiler/tests-dynlink-js/plugin2b.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
let () = print_endline "plugin 2b loaded"
11 changes: 9 additions & 2 deletions runtime/stdlib.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,15 @@ var caml_global_data = [0];
//Requires: caml_jsstring_of_string
function caml_build_symbols(symb) {
var r = {};
var max = -1;
if (symb) {
for (var i = 1; i < symb.length; i++) {
r[caml_jsstring_of_string(symb[i][1])] = symb[i][2];
var idx = symb[i][2];
max = Math.max(max, idx);
r[caml_jsstring_of_string(symb[i][1])] = idx;
}
}
r.next_idx = max + 1;
return r;
}

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

0 comments on commit 4efc86c

Please sign in to comment.