diff --git a/CHANGES.md b/CHANGES.md index dd28336b1bf..9bedcc344ce 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,8 @@ is done to prevent the accidental collision with library dependencies of the executable. (#2364, fixes #2292, @rgrinberg) +- Enable `(explicit_js_mode)` by default. (#1941, @nojb) + 1.11.0 (unreleased) ------------------- @@ -108,6 +110,10 @@ framework with a variable (#2313, @mlasson, original idea by @diml, review by @rgrinberg). +- New binary kind `js` for executables in order to explicitly enable Javascript + targets, and a switch `(explicit_js_mode)` to require this mode in order to + declare JS targets corresponding to executables. (#1941, @nojb) + 1.10.0 (04/06/2019) ------------------- diff --git a/doc/advanced-topics.rst b/doc/advanced-topics.rst index d1e14e24459..bed9886e2b0 100644 --- a/doc/advanced-topics.rst +++ b/doc/advanced-topics.rst @@ -268,6 +268,26 @@ Starting from dune 2.0, dune mangles compilation units of executables by default. However, this can still be turned off using ``(wrapped_executables false)`` +.. _explicit-js-mode: + +Explicit JS mode +================ + +By default, Javascript targets are defined for every bytecode executable that +dune knows about. This is not very precise and does not interact well with the +``@all`` alias (eg, the ``@all`` alias will try to build JS targets +corresponding to every ``test`` stanza). In order to better control the +compilation of JS targets, this behaviour can be turned off by using +``(explicit_js_mode)`` in the ``dune-project`` file. + +When explicit JS mode is enabled, an explicit `js` mode needs to be added to the +``(modes ...)`` field of executables in order to trigger JS +compilation. Explicit JS targets declared like this will be attached to the +``@all`` alias. + +Starting from dune 2.0 this new behaviour will be the default and JS compilation +of binaries will need to be explicitly declared. + .. _dialects-main: Dialects diff --git a/doc/dune-files.rst b/doc/dune-files.rst index b416eb5b11d..cee27469a2f 100644 --- a/doc/dune-files.rst +++ b/doc/dune-files.rst @@ -341,6 +341,8 @@ compilation is not available. - ``shared_object`` for producing object files that can be dynamically loaded into an application. This mode can be used to write a plugin in OCaml for a non-OCaml application. +- ``js`` for producing Javascript from bytecode executables, see + :ref:`explicit-js-mode`. For instance the following ``executables`` stanza will produce byte code executables and native shared objects: @@ -359,6 +361,7 @@ Additionally, you can use the following short-hands: - ``shared_object`` for ``(best shared_object)`` - ``byte`` for ``(byte exe)`` - ``native`` for ``(native exe)`` +- ``js`` for ``(byte js)`` For instance the following ``modes`` fields are all equivalent: @@ -381,6 +384,7 @@ native/best object .exe%{ext_obj} byte shared_object .bc%{ext_dll} native/best shared_object %{ext_dll} byte c .bc.c +byte js .bc.js ================ ============= ================= Where ``%{ext_obj}`` and ``%{ext_dll}`` are the extensions for object diff --git a/dune-project b/dune-project index fb0b076e232..12417bafbff 100644 --- a/dune-project +++ b/dune-project @@ -4,6 +4,7 @@ (implicit_transitive_deps false) (generate_opam_files true) (wrapped_executables true) +(explicit_js_mode) (license MIT) (maintainers "Jane Street Group, LLC ") diff --git a/src/binary_kind.ml b/src/binary_kind.ml index e2c47cc7be8..468d527a436 100644 --- a/src/binary_kind.ml +++ b/src/binary_kind.ml @@ -5,6 +5,7 @@ type t = | Exe | Object | Shared_object + | Js let decode = let open Dune_lang.Decoder in @@ -13,6 +14,7 @@ let decode = ; "exe" , return Exe ; "object" , return Object ; "shared_object" , return Shared_object + ; "js" , Syntax.since Stanza.syntax (1, 11) >>> return Js ] let to_string = function @@ -20,6 +22,7 @@ let to_string = function | Exe -> "exe" | Object -> "object" | Shared_object -> "shared_object" + | Js -> "js" let to_dyn t = let open Dyn.Encoder in @@ -28,4 +31,4 @@ let to_dyn t = let encode t = Dune_lang.unsafe_atom_of_string (to_string t) -let all = [C; Exe; Object; Shared_object] +let all = [C; Exe; Object; Shared_object; Js] diff --git a/src/binary_kind.mli b/src/binary_kind.mli index 6f0778ced55..dbff82f62c7 100644 --- a/src/binary_kind.mli +++ b/src/binary_kind.mli @@ -7,6 +7,7 @@ type t = | Exe | Object | Shared_object + | Js include Dune_lang.Conv with type t := t diff --git a/src/cinaps.ml b/src/cinaps.ml index 0ce41334d45..1a37ab72d03 100644 --- a/src/cinaps.ml +++ b/src/cinaps.ml @@ -127,6 +127,7 @@ let gen_rules sctx t ~dir ~scope ~dir_kind = ~requires_compile:(Lib.Compile.direct_requires compile_info) ~requires_link:(Lib.Compile.requires_link compile_info) ~flags:(Ocaml_flags.of_list ["-w"; "-24"]) + ~js_of_ocaml:None ~dynlink:false ~package:None in diff --git a/src/compilation_context.ml b/src/compilation_context.ml index 5de14abcb38..0b94c4994e2 100644 --- a/src/compilation_context.ml +++ b/src/compilation_context.ml @@ -91,7 +91,7 @@ let create ~super_context ~scope ~expander ~obj_dir ?(dir_kind=Dune_lang.File_syntax.Dune) ~modules ~flags ~requires_compile ~requires_link ?(preprocessing=Preprocessing.dummy) ?(no_keep_locs=false) - ~opaque ?stdlib ?js_of_ocaml ~dynlink ?sandbox ~package ?vimpl () = + ~opaque ?stdlib ~js_of_ocaml ~dynlink ?sandbox ~package ?vimpl () = let requires_compile = if Dune_project.implicit_transitive_deps (Scope.project scope) then Lazy.force requires_link diff --git a/src/compilation_context.mli b/src/compilation_context.mli index 5a06cc841ef..0552416d42e 100644 --- a/src/compilation_context.mli +++ b/src/compilation_context.mli @@ -27,7 +27,7 @@ val create -> ?no_keep_locs : bool -> opaque : bool -> ?stdlib : Dune_file.Library.Stdlib.t - -> ?js_of_ocaml : Dune_file.Js_of_ocaml.t + -> js_of_ocaml : Dune_file.Js_of_ocaml.t option -> dynlink : bool -> ?sandbox : bool -> package : Package.t option diff --git a/src/dune_file.ml b/src/dune_file.ml index 25806c44312..f4a659654f8 100644 --- a/src/dune_file.ml +++ b/src/dune_file.ml @@ -1526,6 +1526,7 @@ module Executables = struct let byte = byte_exe let native = native_exe + let js = make Byte Js let installable_modes = [exe; native; byte] @@ -1536,6 +1537,7 @@ module Executables = struct ; "shared_object" , shared_object ; "byte" , byte ; "native" , native + ; "js" , js ] let simple = @@ -1548,7 +1550,7 @@ module Executables = struct (let+ mode = Mode_conf.decode and+ kind = Binary_kind.decode and+ loc = loc in - { mode; kind; loc})) + {mode; kind; loc})) ~else_:simple let simple_encode link_mode = diff --git a/src/dune_file.mli b/src/dune_file.mli index dcc7822c43c..064e5452c9e 100644 --- a/src/dune_file.mli +++ b/src/dune_file.mli @@ -332,6 +332,8 @@ module Executables : sig val shared_object : t val byte : t val native : t + val byte_exe : t + val js : t val compare : t -> t -> Ordering.t diff --git a/src/dune_project.ml b/src/dune_project.ml index 077549d7a1a..ac0b1934c1e 100644 --- a/src/dune_project.ml +++ b/src/dune_project.ml @@ -209,6 +209,7 @@ type t = ; generate_opam_files : bool ; file_key : File_key.t ; dialects : Dialect.DB.t + ; explicit_js_mode : bool } let equal = (==) @@ -232,6 +233,7 @@ let implicit_transitive_deps t = t.implicit_transitive_deps let allow_approx_merlin t = t.allow_approx_merlin let generate_opam_files t = t.generate_opam_files let dialects t = t.dialects +let explicit_js_mode t = t.explicit_js_mode let to_dyn { name ; root ; version ; source; license; authors @@ -240,7 +242,7 @@ let to_dyn ; extension_args = _; stanza_parser = _ ; packages ; implicit_transitive_deps ; wrapped_executables ; dune_version ; allow_approx_merlin ; generate_opam_files - ; file_key ; dialects } = + ; file_key ; dialects ; explicit_js_mode } = let open Dyn.Encoder in record [ "name", Name.to_dyn name @@ -265,6 +267,7 @@ let to_dyn ; "generate_opam_files", bool generate_opam_files ; "file_key", string file_key ; "dialects", Dialect.DB.to_dyn dialects + ; "explicit_js_mode", bool explicit_js_mode ] let find_extension_args t key = @@ -530,6 +533,9 @@ let implicit_transitive_deps_default ~(lang : Lang.Instance.t) = let wrapped_executables_default ~(lang : Lang.Instance.t) = lang.version >= (2, 0) +let explicit_js_mode_default ~(lang : Lang.Instance.t) = + lang.version >= (2, 0) + let anonymous = lazy ( let lang = get_dune_lang () in let name = Name.anonymous_root in @@ -545,6 +551,7 @@ let anonymous = lazy ( in let implicit_transitive_deps = implicit_transitive_deps_default ~lang in let wrapped_executables = wrapped_executables_default ~lang in + let explicit_js_mode = explicit_js_mode_default ~lang in let root = Path.Source.root in let file_key = File_key.make ~root ~name in { name @@ -569,6 +576,7 @@ let anonymous = lazy ( ; generate_opam_files = false ; file_key ; dialects = Dialect.DB.builtin + ; explicit_js_mode }) let default_name ~dir ~packages = @@ -636,6 +644,8 @@ let parse ~dir ~lang ~opam_packages ~file = ~check:(Syntax.since Stanza.syntax (1, 10)) and+ dialects = multi_field "dialect" (Syntax.since Stanza.syntax (1, 11) >>> located Dialect.decode) + and+ explicit_js_mode = + field_b "explicit_js_mode" ~check:(Syntax.since Stanza.syntax (1, 11)) in let homepage = match homepage, source with @@ -750,6 +760,7 @@ let parse ~dir ~lang ~opam_packages ~file = ; allow_approx_merlin ; generate_opam_files ; dialects + ; explicit_js_mode }) let load_dune_project ~dir opam_packages = @@ -798,6 +809,7 @@ let make_jbuilder_project ~dir opam_packages = ; generate_opam_files = false ; wrapped_executables = false ; dialects + ; explicit_js_mode = false } let load ~dir ~files = diff --git a/src/dune_project.mli b/src/dune_project.mli index 0d154c0afc9..48324b19c26 100644 --- a/src/dune_project.mli +++ b/src/dune_project.mli @@ -83,6 +83,7 @@ val stanza_parser : t -> Stanza.t list Dune_lang.Decoder.t val allow_approx_merlin : t -> bool val generate_opam_files : t -> bool val dialects : t -> Dialect.DB.t +val explicit_js_mode : t -> bool val equal : t -> t -> bool val hash : t -> int diff --git a/src/exe.ml b/src/exe.ml index 3cdb2fd3cf6..cca94cd7954 100644 --- a/src/exe.ml +++ b/src/exe.ml @@ -43,6 +43,12 @@ module Linkage = struct | None -> custom | Some _ -> native + let js = + { mode = Byte + ; ext = ".bc.js" + ; flags = [] + } + let make ~mode ~ext ?(flags=[]) () = { mode ; ext @@ -79,10 +85,15 @@ module Linkage = struct | Native , Object -> ".exe" ^ ctx.lib_config.ext_obj | Byte , Shared_object -> ".bc" ^ ctx.lib_config.ext_dll | Native , Shared_object -> ctx.lib_config.ext_dll + | Byte , Js -> ".bc.js" + | Native , Js -> User_error.raise ~loc:m.loc + [ Pp.text "Javascript generation only \ + supports bytecode!" ] in let flags = match m.kind with | C -> c_flags + | Js -> [] | Exe -> begin match wanted_mode, real_mode with @@ -120,7 +131,7 @@ let link_exe ~loc ~name ~(linkage:Linkage.t) - ~top_sorted_modules + ~cm_files ~link_time_code_gen ~promote ?(link_flags=Build.arr (fun _ -> [])) @@ -129,22 +140,11 @@ let link_exe let sctx = CC.super_context cctx in let ctx = SC.context sctx in let dir = CC.dir cctx in - let obj_dir = CC.obj_dir cctx in let requires = CC.requires_link cctx in - let expander = CC.expander cctx in let mode = linkage.mode in let exe = exe_path_from_name cctx ~name ~linkage in let compiler = Option.value_exn (Context.compiler ctx mode) in - let js_of_ocaml = - CC.js_of_ocaml cctx - |> Option.value ~default:Dune_file.Js_of_ocaml.default - in - let cm_files = - let modules = CC.modules cctx in - Cm_files.make ~obj_dir ~modules ~top_sorted_modules - ~ext_obj:ctx.lib_config.ext_obj - in - let top_sorted_cms = Cm_files.top_sorted_cms cm_files ~mode in + let top_sorted_cms = Cm_files.top_sorted_cms cm_files ~mode:linkage.mode in SC.add_rule sctx ~loc ~dir ~mode:(match promote with | None -> Standard @@ -181,15 +181,24 @@ let link_exe ; Lib.Lib_and_module.L.link_flags to_link ~mode ]) ; Dyn (Build.S.map top_sorted_cms ~f:(fun x -> Command.Args.Deps x)) - ])); - if linkage.ext = ".bc" then - let flags = - (Expander.expand_and_eval_set expander - js_of_ocaml.flags - ~standard:(Build.return (Js_of_ocaml_rules.standard sctx))) in - Js_of_ocaml_rules.build_exe cctx ~js_of_ocaml ~src:exe - ~cm:top_sorted_cms ~flags:(Command.Args.dyn flags) - ~promote + ])) + +let link_js ~name ~cm_files ~promote cctx = + let sctx = CC.super_context cctx in + let expander = CC.expander cctx in + let js_of_ocaml = + CC.js_of_ocaml cctx + |> Option.value ~default:Dune_file.Js_of_ocaml.default + in + let src = exe_path_from_name cctx ~name ~linkage:Linkage.byte in + let flags = + (Expander.expand_and_eval_set expander + js_of_ocaml.flags + ~standard:(Build.return (Js_of_ocaml_rules.standard sctx))) in + let top_sorted_cms = Cm_files.top_sorted_cms cm_files ~mode:Mode.Byte in + Js_of_ocaml_rules.build_exe cctx ~js_of_ocaml ~src + ~cm:top_sorted_cms ~flags:(Command.Args.dyn flags) + ~promote let build_and_link_many ~programs @@ -203,22 +212,32 @@ let build_and_link_many Module_compilation.build_all cctx ~dep_graphs; let link_time_code_gen = Link_time_code_gen.handle_special_libs cctx in - let modules = Compilation_context.modules cctx in List.iter programs ~f:(fun { Program.name; main_module_name ; loc } -> - let top_sorted_modules = - let main = Option.value_exn (Modules.find modules main_module_name) in - Dep_graph.top_closed_implementations dep_graphs.impl - [main] + let cm_files = + let sctx = CC.super_context cctx in + let ctx = SC.context sctx in + let obj_dir = CC.obj_dir cctx in + let top_sorted_modules = + let main = Option.value_exn (Modules.find modules main_module_name) in + Dep_graph.top_closed_implementations dep_graphs.impl + [main] + in + Cm_files.make ~obj_dir ~modules ~top_sorted_modules + ~ext_obj:ctx.lib_config.ext_obj in List.iter linkages ~f:(fun linkage -> - link_exe cctx - ~loc - ~name - ~linkage - ~top_sorted_modules - ~link_time_code_gen - ~promote - ?link_flags)) + if linkage = Linkage.js then + link_js ~name ~cm_files ~promote cctx + else + link_exe cctx + ~loc + ~name + ~linkage + ~cm_files + ~link_time_code_gen + ~promote + ?link_flags + )) let build_and_link ~program = build_and_link_many ~programs:[program] diff --git a/src/exe.mli b/src/exe.mli index f8c6f5b41e0..0bbf6ed3270 100644 --- a/src/exe.mli +++ b/src/exe.mli @@ -24,6 +24,9 @@ module Linkage : sig (** [native] if supported, [custom] if not *) val native_or_custom : Context.t -> t + (** Javascript compilation, extension [.bc.js] *) + val js : t + val make : mode:Mode.t -> ext:string diff --git a/src/exe_rules.ml b/src/exe_rules.ml index 982f17d8f72..834afab21e9 100644 --- a/src/exe_rules.ml +++ b/src/exe_rules.ml @@ -53,12 +53,23 @@ let executables_rules ~sctx ~dir ~dir_kind ~expander ]) in + let explicit_js_mode = Dune_project.explicit_js_mode (Scope.project scope) in + let linkages = let module L = Dune_file.Executables.Link_mode in let ctx = SC.context sctx in let l = let has_native = Option.is_some ctx.ocamlopt in - List.filter_map (L.Set.to_list exes.modes) ~f:(fun (mode : L.t) -> + let modes = + let f = function {L.kind = Js; _} -> true | _ -> false in + if L.Set.exists exes.modes ~f then + L.Set.add exes.modes L.byte_exe + else if not explicit_js_mode && L.Set.mem exes.modes L.byte_exe then + L.Set.add exes.modes L.js + else + exes.modes + in + List.filter_map (L.Set.to_list modes) ~f:(fun (mode : L.t) -> match has_native, mode.mode with | false, Native -> None @@ -86,6 +97,13 @@ let executables_rules ~sctx ~dir ~dir_kind ~expander let cctx = let requires_compile = Lib.Compile.direct_requires compile_info in let requires_link = Lib.Compile.requires_link compile_info in + let js_of_ocaml = + let js_of_ocaml = exes.buildable.js_of_ocaml in + if explicit_js_mode then + Option.some_if (List.mem ~set:linkages Exe.Linkage.js) js_of_ocaml + else + Some js_of_ocaml + in let dynlink = Dune_file.Executables.Link_mode.Set.exists exes.modes ~f:(fun mode -> match mode.kind with @@ -103,7 +121,7 @@ let executables_rules ~sctx ~dir ~dir_kind ~expander ~requires_link ~requires_compile ~preprocessing:pp - ~js_of_ocaml:exes.buildable.js_of_ocaml + ~js_of_ocaml ~opaque:(SC.opaque sctx) ~dynlink ~package:exes.package diff --git a/src/gen_rules.ml b/src/gen_rules.ml index d6221d2deaa..4c97168d53c 100644 --- a/src/gen_rules.ml +++ b/src/gen_rules.ml @@ -216,6 +216,7 @@ module Gen(P : sig val sctx : Super_context.t end) = struct |> SC.add_rules ~dir:ctx_dir sctx | _ -> ()); let dyn_deps = + (* DUNE2: no need to filter out js targets anymore *) let pred = let id = lazy ( let open Dyn.Encoder in @@ -225,9 +226,15 @@ module Gen(P : sig val sctx : Super_context.t end) = struct List.iter js_targets ~f:(fun js_target -> assert (Path.Build.equal (Path.Build.parent_exn js_target) ctx_dir)); - Predicate.create ~id ~f:(fun basename -> - not (List.exists js_targets ~f:(fun js_target -> - String.equal (Path.Build.basename js_target) basename))) + let f = + if Dune_project.explicit_js_mode (Scope.project scope) then + fun _ -> true + else + fun basename -> + not (List.exists js_targets ~f:(fun js_target -> + String.equal (Path.Build.basename js_target) basename)) + in + Predicate.create ~id ~f in File_selector.create ~dir:(Path.build ctx_dir) pred |> Build.paths_matching ~loc:Loc.none diff --git a/src/inline_tests.ml b/src/inline_tests.ml index d65ba3470cc..6bcc993ecab 100644 --- a/src/inline_tests.ml +++ b/src/inline_tests.ml @@ -292,7 +292,7 @@ include Sub_system.Register_end_point( ~requires_compile:runner_libs ~requires_link:(lazy runner_libs) ~flags:(Ocaml_flags.of_list ["-w"; "-24"; "-g"]) - ~js_of_ocaml:lib.buildable.js_of_ocaml + ~js_of_ocaml:(Some lib.buildable.js_of_ocaml) ~dynlink:false ~package:(Option.map lib.public ~f:(fun p -> p.package)); in @@ -302,12 +302,12 @@ include Sub_system.Register_end_point( then Mode_conf.Set.add info.modes Byte else info.modes in - List.filter_map (Mode_conf.Set.to_list modes) ~f:(fun (mode : Mode_conf.t) -> + List.map (Mode_conf.Set.to_list modes) ~f:(fun (mode : Mode_conf.t) -> match mode with - | Native -> Some Exe.Linkage.native - | Best -> Some (Exe.Linkage.native_or_custom (Super_context.context sctx)) - | Byte -> Some Exe.Linkage.byte - | Javascript -> None + | Native -> Exe.Linkage.native + | Best -> Exe.Linkage.native_or_custom (Super_context.context sctx) + | Byte -> Exe.Linkage.byte + | Javascript -> Exe.Linkage.js ) in Exe.build_and_link cctx diff --git a/src/lib_rules.ml b/src/lib_rules.ml index 2a36a0778fb..23ff418730e 100644 --- a/src/lib_rules.ml +++ b/src/lib_rules.ml @@ -370,7 +370,7 @@ module Gen (P : sig val sctx : Super_context.t end) = struct ~preprocessing:pp ~no_keep_locs:lib.no_keep_locs ~opaque - ~js_of_ocaml:lib.buildable.js_of_ocaml + ~js_of_ocaml:(Some lib.buildable.js_of_ocaml) ~dynlink ?stdlib:lib.stdlib ~package:(Option.map lib.public ~f:(fun p -> p.package)) diff --git a/src/link_time_code_gen.ml b/src/link_time_code_gen.ml index 898ec26a2e0..8333d92a0f0 100644 --- a/src/link_time_code_gen.ml +++ b/src/link_time_code_gen.ml @@ -55,6 +55,7 @@ let generate_and_compile_module cctx ~precompiled_cmi ~name:basename ~requires_link:(lazy requires) ~flags:Ocaml_flags.empty ~opaque + ~js_of_ocaml:None ~dynlink:(Compilation_context.dynlink cctx) ~package:(Compilation_context.package cctx) () diff --git a/src/toplevel.ml b/src/toplevel.ml index 1750aab8c97..fdf06f07d3b 100644 --- a/src/toplevel.ml +++ b/src/toplevel.ml @@ -144,6 +144,7 @@ module Stanza = struct ~requires_compile ~requires_link ~flags + ~js_of_ocaml:None ~dynlink:false ~package:None in diff --git a/src/utop.ml b/src/utop.ml index 81fd1b171e9..a4215a77003 100644 --- a/src/utop.ml +++ b/src/utop.ml @@ -91,6 +91,7 @@ let setup sctx ~dir = ~requires_link:(lazy requires) ~requires_compile:requires ~flags + ~js_of_ocaml:None ~dynlink:false ~package:None in diff --git a/test/blackbox-tests/dune.inc b/test/blackbox-tests/dune.inc index d1f221421e0..f8af5fd88a9 100644 --- a/test/blackbox-tests/dune.inc +++ b/test/blackbox-tests/dune.inc @@ -467,6 +467,14 @@ test-cases/exec-missing (progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected))))) +(alias + (name explicit_js_mode) + (deps (package dune) (source_tree test-cases/explicit_js_mode)) + (action + (chdir + test-cases/explicit_js_mode + (progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected))))) + (alias (name external-lib-deps) (deps (package dune) (source_tree test-cases/external-lib-deps)) @@ -2019,6 +2027,6 @@ (name runtest-disabled) (deps (alias cinaps) (alias envs-and-contexts))) -(alias (name runtest-js) (deps (alias js_of_ocaml))) +(alias (name runtest-js) (deps (alias explicit_js_mode) (alias js_of_ocaml))) (alias (name runtest-coq) (deps (alias coq))) \ No newline at end of file diff --git a/test/blackbox-tests/gen_tests.ml b/test/blackbox-tests/gen_tests.ml index 1d4943991db..ced5bd8e9de 100644 --- a/test/blackbox-tests/gen_tests.ml +++ b/test/blackbox-tests/gen_tests.ml @@ -165,6 +165,7 @@ let exclusions = ; make "env" ~skip_ocaml:"<4.06.0" ; make "env-cflags" ~skip_ocaml:"<4.06.0" ; make "wrapped-transition" ~skip_ocaml:"<4.06.0" + ; make "explicit_js_mode" ~external_deps:true ~js:true ] let all_tests = lazy ( diff --git a/test/blackbox-tests/test-cases/explicit_js_mode/a.ml b/test/blackbox-tests/test-cases/explicit_js_mode/a.ml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/explicit_js_mode/b.ml b/test/blackbox-tests/test-cases/explicit_js_mode/b.ml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/explicit_js_mode/c.ml b/test/blackbox-tests/test-cases/explicit_js_mode/c.ml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/explicit_js_mode/d.ml b/test/blackbox-tests/test-cases/explicit_js_mode/d.ml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/explicit_js_mode/dune b/test/blackbox-tests/test-cases/explicit_js_mode/dune new file mode 100644 index 00000000000..ceefe483d31 --- /dev/null +++ b/test/blackbox-tests/test-cases/explicit_js_mode/dune @@ -0,0 +1,22 @@ +(executable + (name a) + (modules a)) + +(executable + (name b) + (modes js) + (modules b)) + +(library + (name foo) + (modules c)) + +(test + (name d) + (modules d)) + +(executable + (name e) + (modules e) + (modes js) + (libraries foo)) diff --git a/test/blackbox-tests/test-cases/explicit_js_mode/dune-project b/test/blackbox-tests/test-cases/explicit_js_mode/dune-project new file mode 100644 index 00000000000..46c66d56fe1 --- /dev/null +++ b/test/blackbox-tests/test-cases/explicit_js_mode/dune-project @@ -0,0 +1,2 @@ +(lang dune 1.11) +(explicit_js_mode) diff --git a/test/blackbox-tests/test-cases/explicit_js_mode/e.ml b/test/blackbox-tests/test-cases/explicit_js_mode/e.ml new file mode 100755 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/explicit_js_mode/run.t b/test/blackbox-tests/test-cases/explicit_js_mode/run.t new file mode 100644 index 00000000000..a52f4befdf9 --- /dev/null +++ b/test/blackbox-tests/test-cases/explicit_js_mode/run.t @@ -0,0 +1,58 @@ +Check that .bc.js rule is generated only if js mode is used. + + $ dune build --display short a.bc.js + Error: Don't know how to build a.bc.js + Hint: did you mean b.bc.js or e.bc.js? + [1] + + $ dune build --display short b.bc.js + js_of_ocaml b.bc.runtime.js + ocamldep .b.eobjs/b.ml.d + ocamlc .b.eobjs/byte/b.{cmi,cmo,cmt} + js_of_ocaml .b.eobjs/byte/b.cmo.js + js_of_ocaml .js/stdlib/stdlib.cma.js + jsoo_link b.bc.js + +We also check that .cmo.js rules are not generated if not specified. + + $ dune build --display short _build/default/.a.eobjs/byte/a.cmo.js + Error: Don't know how to build _build/default/.a.eobjs/byte/a.cmo.js + [1] + +JS compilation of libraries is always available to avoid having to annotate +every dependency of an executable. + + $ dune build --display short _build/default/.foo.objs/foo.cma.js + ocamlc .foo.objs/byte/foo.{cmi,cmo,cmt} + ocamldep .foo.objs/c.ml.d + ocamlc .foo.objs/byte/foo__C.{cmi,cmo,cmt} + ocamlc foo.cma + js_of_ocaml .foo.objs/foo.cma.js + +Check that js targets are attached to @all, but not for tests that do not +specify js mode (#1940). + + $ dune clean + $ dune build --display short @@all 2>&1 | grep js_of_ocaml + js_of_ocaml b.bc.runtime.js + js_of_ocaml .b.eobjs/byte/b.cmo.js + js_of_ocaml e.bc.runtime.js + js_of_ocaml .e.eobjs/byte/e.cmo.js + js_of_ocaml .js/stdlib/stdlib.cma.js + js_of_ocaml .foo.objs/foo.cma.js + +Check that building a JS-enabled executable that depends on a library works. + + $ dune clean + $ dune build --display short e.bc.js + js_of_ocaml e.bc.runtime.js + ocamldep .e.eobjs/e.ml.d + ocamlc .foo.objs/byte/foo.{cmi,cmo,cmt} + ocamldep .foo.objs/c.ml.d + ocamlc .foo.objs/byte/foo__C.{cmi,cmo,cmt} + ocamlc foo.cma + js_of_ocaml .foo.objs/foo.cma.js + js_of_ocaml .js/stdlib/stdlib.cma.js + ocamlc .e.eobjs/byte/e.{cmi,cmo,cmt} + js_of_ocaml .e.eobjs/byte/e.cmo.js + jsoo_link e.bc.js