|
| 1 | += Runtime files = |
| 2 | + |
| 3 | +For compiling a bytecode executable to JavaScript, one often need to pass |
| 4 | +JavaScript runtime files for some OCaml libraries used by the |
| 5 | +executable. Tracking the required runtime files is done using the de-facto |
| 6 | +standard for library management in OCaml, Findlib. |
| 7 | + |
| 8 | + |
| 9 | +== Listing js runtime files |
| 10 | + |
| 11 | +To list all JavaScript runtime files for a set of libraries: |
| 12 | + |
| 13 | +{{{ |
| 14 | + ocamlfind query -format "%+(jsoo_runtime)" -r LIB1 LIB2 ... | grep -v "^$" |
| 15 | +}}} |
| 16 | + |
| 17 | +For example, for **base** and **time_now** |
| 18 | + |
| 19 | +{{{ |
| 20 | + $ ocamlfind query -format "%+(jsoo_runtime)" -r base time_now | grep -v "^$" |
| 21 | + ~/.opam/4.14.0/lib/base/base_internalhash_types/runtime.js |
| 22 | + ~/.opam/4.14.0/lib/base/runtime.js |
| 23 | + ~/.opam/4.14.0/lib/time_now/runtime.js |
| 24 | +}}} |
| 25 | + |
| 26 | +Here is minimal example of manually compiling a single ml file program: |
| 27 | +{{{ |
| 28 | + $ export LIBS=base,time_now |
| 29 | + $ ocamlfind ocamlc -package $LIBS -linkpkg main.ml -o main.byte |
| 30 | + $ js_of_ocaml $(ocamlfind query -format "%+(jsoo_runtime)" -r $LIBS) main.byte |
| 31 | +}}} |
| 32 | + |
| 33 | +== Declaring runtime JavaScript files inside a META file |
| 34 | + |
| 35 | +The **jsoo_runtime** variable is used to declare one or more runtime files. |
| 36 | +Files must be coma-separated and should be plain names relative to the package directory. |
| 37 | + |
| 38 | +For example, to declare that **mypackage.sublib** requires the file **mypackage/subdir/runtime.js** |
| 39 | +{{{ |
| 40 | + cat mypackage/META |
| 41 | + package "sublib" ( |
| 42 | + directory = "subdir" |
| 43 | + jsoo_runtime = "runtime.js" |
| 44 | + ) |
| 45 | +}}} |
| 46 | + |
| 47 | +While the mechanism allows arbitrary naming for the javascript files, |
| 48 | +if there is only one file, we suggest naming it **runtime.js** by |
| 49 | +convention. |
| 50 | + |
| 51 | +== The old deprecated way |
| 52 | + |
| 53 | +Before dune and its native support for js_of_ocaml, the (hacky) way |
| 54 | +to rely on Findlib was to use a **linkopts** variable with a **javascript** |
| 55 | +predicate {{{linkopts(javascript)}}} and have js_of_ocaml be responsible for |
| 56 | +looking up the files in the right directory. |
| 57 | + |
| 58 | +This approach is not very satisfying: |
| 59 | +* It makes it harder for a build system to know the set of dependencies. |
| 60 | +* The js_of_ocaml compiler needs to perform findlib resolution itself. |
| 61 | +
|
| 62 | +=== Listing linkopts |
| 63 | + |
| 64 | +To list all {{{linkopts(javascript)}}} for a set of libraries: |
| 65 | + |
| 66 | +{{{ |
| 67 | + ocamlfind query -o-format -r -predicates javascript LIB1 LIB2 ... |
| 68 | +}}} |
| 69 | + |
| 70 | +For example, for **base** and **time_now** |
| 71 | + |
| 72 | +{{{ |
| 73 | + $ ocamlfind query -o-format -r -predicates javascript base time_now |
| 74 | + +base/base_internalhash_types/runtime.js |
| 75 | + +base/runtime.js |
| 76 | + +time_now/runtime.js |
| 77 | +}}} |
| 78 | + |
| 79 | +=== Declaring runtime JavaScript files inside META files |
| 80 | + |
| 81 | +The content of {{{linkopts(javascript)}}} is given directly to the |
| 82 | +js_of_ocaml compiler. To be able reference files independently of the |
| 83 | +installation path, we rely on js_of_ocaml's findlib support (see Command-Line findlib support below). |
| 84 | + |
| 85 | +For example, to declare that **mypackage.sublib** requires the file **mypackage/subdir/runtime.js** |
| 86 | + |
| 87 | +{{{ |
| 88 | + cat mypackage/META |
| 89 | + package "sublib" ( |
| 90 | + directory = "subdir" |
| 91 | + linkopts(javascript) = "+mypackage/sublib/runtime.js" |
| 92 | + ) |
| 93 | +}}} |
| 94 | + |
| 95 | +== Command line findlib support (deprecated) |
| 96 | +If js_of_ocaml is compiled with findlib support, one can use the |
| 97 | +following syntax to reference JavaScript files: |
| 98 | +* {{{ +{findlib-package}/{javascript-file} }}} |
| 99 | +* {{{ +{javascript-file} }}} |
| 100 | +
|
| 101 | +The file **javascript-file** will be looked up inside the **findlib-package** lib directory. |
| 102 | + |
| 103 | +When no package is provided, the compiler will look inside js_of_ocaml-compiler lib directory. |
| 104 | + |
| 105 | +For example, if findlib install all libraries inside ${LIBDIR}: |
| 106 | +* {{{+mypackage/jsfile.js}}} resolves to {{{${LIBDIR}/mypackage/jsfile.js}}} |
| 107 | +* {{{+mypackage/dir/jsfile.js}}} resolves to {{{${LIBDIR}/mypackage/dir/jsfile.js}}} |
| 108 | +* {{{+toplevel.js}}} resolves to {{{${LIBDIR}/js_of_ocaml-compiler/jsfile.js}}} |
| 109 | +
|
| 110 | +== Compatibility |
| 111 | + |
| 112 | +**dune** generate META files that are usable with the old deprecated |
| 113 | +way. However, it only uses **jsoo_runtime** to look up information. |
| 114 | + |
| 115 | +**js_of_ocaml-ocamlbuild** uses **jsoo_runtime** by default starting with version 5.0. |
0 commit comments