Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate linkall to js_of_ocaml for separate compilation #6832

Merged
merged 2 commits into from
Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ Unreleased
- Fix *js_of_ocaml* separate compilation rules when `--enable=effects`
or `--enable=use-js-string` is used. (#6714, #6828, @hhugo)

- Fix *js_of_ocaml* separate compilation in presence of linkall (#6832, @hhugo)

- Remove spurious build dir created when running `dune init proj ...` (#6707,
fixes #5429, @gridbugs)

Expand Down
6 changes: 6 additions & 0 deletions src/dune_rules/command.mli
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,9 @@ end
command in directory [dir]. *)
val expand :
dir:Path.t -> 'a Args.t -> string list Action_builder.With_targets.t

(** [expand_no_targets ~dir args] interprets the command line arguments [args]
to produce corresponding strings, assuming they will be used as arguments to
run a command in directory [dir]. *)
val expand_no_targets :
dir:Path.t -> Args.without_targets Args.t -> string list Action_builder.t
1 change: 1 addition & 0 deletions src/dune_rules/dune_rules.ml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module Modules = Modules
module Module_compilation = Module_compilation
module Exe_rules = Exe_rules
module Lib_rules = Lib_rules
module Jsoo_rules = Jsoo_rules
rgrinberg marked this conversation as resolved.
Show resolved Hide resolved
module Obj_dir = Obj_dir
module Merlin_ident = Merlin_ident
module Merlin = Merlin
Expand Down
25 changes: 13 additions & 12 deletions src/dune_rules/exe.ml
Original file line number Diff line number Diff line change
Expand Up @@ -202,21 +202,22 @@ let link_exe ~loc ~name ~(linkage : Linkage.t) ~cm_files ~link_time_code_gen
| Some p -> Promote p)
action_with_targets

let link_js ~name ~loc ~obj_dir ~top_sorted_modules ~promote ~link_time_code_gen
cctx =
let link_js ~name ~loc ~obj_dir ~top_sorted_modules ~link_args ~promote
~link_time_code_gen cctx =
let in_context =
CC.js_of_ocaml cctx |> Option.value ~default:Js_of_ocaml.In_context.default
in
let link_time_code_gen =
let open Memo.O in
let+ { Link_time_code_gen.to_link; force_linkall = _ } =
Resolve.read_memo link_time_code_gen
in
to_link
in
let src = exe_path_from_name cctx ~name ~linkage:Linkage.byte_for_jsoo in
let linkall =
Action_builder.bind link_args ~f:(fun cmd ->
let open Action_builder.O in
let+ l =
Command.expand_no_targets ~dir:(Path.build (CC.dir cctx)) cmd
in
List.exists l ~f:(String.equal "--linkall"))
in
Jsoo_rules.build_exe cctx ~loc ~obj_dir ~in_context ~src ~top_sorted_modules
~promote ~link_time_code_gen
~promote ~link_time_code_gen ~linkall

type dep_graphs = { for_exes : Module.t list Action_builder.t list }

Expand Down Expand Up @@ -258,8 +259,8 @@ let link_many ?(link_args = Action_builder.return Command.Args.empty) ?o_files
Memo.parallel_iter linkages ~f:(fun linkage ->
if Linkage.is_js linkage then
let obj_dir = CC.obj_dir cctx in
link_js ~loc ~name ~obj_dir ~top_sorted_modules ~promote cctx
~link_time_code_gen
link_js ~loc ~name ~obj_dir ~top_sorted_modules ~promote
~link_args cctx ~link_time_code_gen
else
let* link_time_code_gen =
match Linkage.is_plugin linkage with
Expand Down
152 changes: 103 additions & 49 deletions src/dune_rules/jsoo/jsoo_rules.ml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,49 @@ end = struct
| name, false -> [ "--disable"; name ])
end

module Version = struct
type t = int * int

let of_string s : t option =
let s =
match
String.findi s ~f:(function
| '+' | '-' | '~' -> true
| _ -> false)
with
| None -> s
| Some i -> String.take s i
in
try
match String.split s ~on:'.' with
| [] -> None
| [ major ] -> Some (int_of_string major, 0)
| major :: minor :: _ -> Some (int_of_string major, int_of_string minor)
with _ -> None

let compare (ma1, mi1) (ma2, mi2) =
match Int.compare ma1 ma2 with
| Eq -> Int.compare mi1 mi2
| n -> n

let impl_version bin =
let open Memo.O in
let* _ = Build_system.build_file bin in
Memo.of_reproducible_fiber
@@ Process.run_capture_line Process.Strict bin [ "--version" ]
|> Memo.map ~f:of_string

let version_memo =
Memo.create "jsoo-version" ~input:(module Path) impl_version

let jsoo_version path =
let open Memo.O in
let* jsoo = path in
match jsoo with
| Ok jsoo_path -> Memo.exec version_memo jsoo_path
| Error e -> Action.Prog.Not_found.raise e
end

let install_jsoo_hint = "opam install js_of_ocaml-compiler"

let in_build_dir ~sctx ~config args =
Expand Down Expand Up @@ -202,61 +245,72 @@ let jsoo_archives ~sctx config lib =
; with_js_ext (Path.basename archive)
]))

let link_rule cc ~runtime ~target ~obj_dir cm ~flags ~link_time_code_gen =
let link_rule cc ~runtime ~target ~obj_dir cm ~flags ~linkall
~link_time_code_gen =
let sctx = Compilation_context.super_context cc in
let dir = Compilation_context.dir cc in
let requires = Compilation_context.requires_link cc in
let special_units = Action_builder.of_memo link_time_code_gen in
let config =
Action_builder.of_memo_join
(Memo.map
~f:(fun x -> x.compile)
(Super_context.js_of_ocaml_flags sctx ~dir flags))
|> Action_builder.map ~f:Config.of_flags
in
let mod_name m =
Module_name.Unique.artifact_filename (Module.obj_name m)
~ext:Js_of_ocaml.Ext.cmo
in
let get_all =
Action_builder.map
(Action_builder.both (Action_builder.both cm special_units) config)
~f:(fun ((cm, special_units), config) ->
Resolve.Memo.args
(let open Resolve.Memo.O in
let+ libs = requires in
(* Special case for the stdlib because it is not referenced in the
META *)
let stdlib =
Path.build
(in_build_dir ~sctx ~config
[ "stdlib"; "stdlib" ^ Js_of_ocaml.Ext.cma ])
in
let special_units =
List.concat_map special_units ~f:(function
| Lib_flags.Lib_and_module.Lib _lib -> []
| Module (obj_dir, m) ->
[ in_obj_dir' ~obj_dir ~config:None [ mod_name m ] ])
in
let all_libs = List.concat_map libs ~f:(jsoo_archives ~sctx config) in
let open Action_builder.O in
let+ config =
Action_builder.of_memo_join
(Memo.map
~f:(fun x -> x.compile)
(Super_context.js_of_ocaml_flags sctx ~dir flags))
|> Action_builder.map ~f:Config.of_flags
and+ cm = cm
and+ linkall = linkall
and+ libs = Resolve.Memo.read (Compilation_context.requires_link cc)
and+ { Link_time_code_gen_type.to_link; force_linkall } =
Resolve.read link_time_code_gen
and+ jsoo_version =
Action_builder.of_memo (Version.jsoo_version (jsoo ~dir sctx))
in
(* Special case for the stdlib because it is not referenced in the
META *)
let stdlib =
Path.build
(in_build_dir ~sctx ~config
[ "stdlib"; "stdlib" ^ Js_of_ocaml.Ext.cma ])
in
let special_units =
List.concat_map to_link ~f:(function
| Lib_flags.Lib_and_module.Lib _lib -> []
| Module (obj_dir, m) ->
[ in_obj_dir' ~obj_dir ~config:None [ mod_name m ] ])
in
let all_libs = List.concat_map libs ~f:(jsoo_archives ~sctx config) in

let all_other_modules =
List.map cm ~f:(fun m ->
Path.build (in_obj_dir ~obj_dir ~config:None [ mod_name m ]))
in
let std_exit =
Path.build
(in_build_dir ~sctx ~config
[ "stdlib"; "std_exit" ^ Js_of_ocaml.Ext.cmo ])
in
Command.Args.Deps
(List.concat
[ [ stdlib ]
; special_units
; all_libs
; all_other_modules
; [ std_exit ]
])))
let all_other_modules =
List.map cm ~f:(fun m ->
Path.build (in_obj_dir ~obj_dir ~config:None [ mod_name m ]))
in
let std_exit =
Path.build
(in_build_dir ~sctx ~config
[ "stdlib"; "std_exit" ^ Js_of_ocaml.Ext.cmo ])
in
let linkall = force_linkall || linkall in
Command.Args.S
[ Deps
(List.concat
[ [ stdlib ]
; special_units
; all_libs
; all_other_modules
; [ std_exit ]
])
; As
(match (jsoo_version, linkall) with
| Some version, true -> (
match Version.compare version (5, 1) with
| Lt -> []
| Gt | Eq -> [ "--linkall" ])
| None, _ | _, false -> [])
]
in
let spec = Command.Args.S [ Dep (Path.build runtime); Dyn get_all ] in
js_of_ocaml_rule sctx ~sub_command:Link ~dir ~spec ~target ~flags ~config:None
Expand Down Expand Up @@ -319,7 +373,7 @@ let setup_separate_compilation_rules sctx components =
>>= Super_context.add_rule sctx ~dir))

let build_exe cc ~loc ~in_context ~src ~(obj_dir : Path.Build.t Obj_dir.t)
~(top_sorted_modules : Module.t list Action_builder.t) ~promote
~(top_sorted_modules : Module.t list Action_builder.t) ~promote ~linkall
~link_time_code_gen =
let sctx = Compilation_context.super_context cc in
let dir = Compilation_context.dir cc in
Expand All @@ -344,7 +398,7 @@ let build_exe cc ~loc ~in_context ~src ~(obj_dir : Path.Build.t Obj_dir.t)
~flags
>>= Super_context.add_rule ~loc sctx ~dir
>>> link_rule cc ~runtime:standalone_runtime ~target ~obj_dir
top_sorted_modules ~flags ~link_time_code_gen
top_sorted_modules ~flags ~linkall ~link_time_code_gen
>>= Super_context.add_rule sctx ~loc ~dir ~mode
| Whole_program ->
exe_rule cc ~javascript_files ~src ~target ~flags
Expand Down
11 changes: 10 additions & 1 deletion src/dune_rules/jsoo/jsoo_rules.mli
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ module Config : sig
val all : t list
end

module Version : sig
type t = int * int

val of_string : string -> t option

val compare : t -> t -> Ordering.t
end

val build_cm :
Super_context.t
-> dir:Path.Build.t
Expand All @@ -25,7 +33,8 @@ val build_exe :
-> obj_dir:Path.Build.t Obj_dir.t
-> top_sorted_modules:Module.t list Action_builder.t
-> promote:Rule.Promote.t option
-> link_time_code_gen:Lib_flags.Lib_and_module.L.t Memo.t
-> linkall:bool Action_builder.t
-> link_time_code_gen:Link_time_code_gen_type.t Resolve.t
-> unit Memo.t

val setup_separate_compilation_rules :
Expand Down
2 changes: 1 addition & 1 deletion src/dune_rules/link_time_code_gen.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
open Import

type t =
type t = Link_time_code_gen_type.t =
{ to_link : Lib_flags.Lib_and_module.L.t
; force_linkall : bool
}
Expand Down
2 changes: 1 addition & 1 deletion src/dune_rules/link_time_code_gen.mli
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(** {1 Handle link time code generation} *)

type t =
type t = Link_time_code_gen_type.t =
{ to_link : Lib_flags.Lib_and_module.L.t
; force_linkall : bool
}
Expand Down
6 changes: 6 additions & 0 deletions src/dune_rules/link_time_code_gen_type.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
open! Import

type t =
{ to_link : Lib_flags.Lib_and_module.L.t
; force_linkall : bool
}
6 changes: 6 additions & 0 deletions src/dune_rules/link_time_code_gen_type.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
open! Import

type t =
{ to_link : Lib_flags.Lib_and_module.L.t
; force_linkall : bool
}
4 changes: 2 additions & 2 deletions test/blackbox-tests/test-cases/jsoo/inline-tests.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ Run inline tests using node js
$ dune runtest
inline tests (Byte)
inline tests (Byte)
inline tests (JS)
inline tests (JS)
inline tests (Native)
inline tests (Native)
inline tests (JS)
inline tests (JS)

$ dune runtest --profile release
inline tests (JS)
Expand Down
4 changes: 2 additions & 2 deletions test/blackbox-tests/test-cases/jsoo/jsoo-config.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ tests js_of_ocaml conigs

$ dune build bin/bin1.bc.js bin/bin2.bc.js bin/bin3.bc.js --display short
js_of_ocaml bin/.bin1.eobjs/jsoo/bin1.bc.runtime.js
js_of_ocaml bin/.bin2.eobjs/jsoo/bin2.bc.runtime.js
js_of_ocaml bin/.bin3.eobjs/jsoo/bin3.bc.runtime.js
js_of_ocaml .js/use-js-string/stdlib/std_exit.cmo.js
js_of_ocaml .js/use-js-string/stdlib/stdlib.cma.js
ocamlc lib/.library1.objs/byte/library1.{cmi,cmo,cmt}
js_of_ocaml bin/.bin2.eobjs/jsoo/bin2.bc.runtime.js
js_of_ocaml .js/!use-js-string/stdlib/std_exit.cmo.js
js_of_ocaml .js/!use-js-string/stdlib/stdlib.cma.js
js_of_ocaml bin/.bin3.eobjs/jsoo/bin3.bc.runtime.js
js_of_ocaml .js/default/stdlib/std_exit.cmo.js
js_of_ocaml .js/default/stdlib/stdlib.cma.js
ocamlc bin/.bin1.eobjs/byte/dune__exe__Bin1.{cmi,cmti}
Expand Down
6 changes: 3 additions & 3 deletions test/blackbox-tests/test-cases/jsoo/no-check-prim.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ Compilation using jsoo
ocamlopt lib/.x.objs/native/x__.{cmx,o}
ocamlc lib/.x.objs/byte/x.{cmi,cmo,cmt}
ocamlopt lib/.x.objs/native/x__Y.{cmx,o}
ocamlc bin/.technologic.eobjs/byte/z.{cmi,cmo,cmt}
ocamlopt lib/.x.objs/native/x.{cmx,o}
ocamlc bin/.technologic.eobjs/byte/z.{cmi,cmo,cmt}
ocamlc lib/x.cma
ocamlc bin/.technologic.eobjs/byte/technologic.{cmi,cmo,cmt}
ocamlopt lib/x.{a,cmxa}
js_of_ocaml bin/technologic.bc.js
ocamlc bin/.technologic.eobjs/byte/technologic.{cmi,cmo,cmt}
ocamlopt lib/x.cmxs
js_of_ocaml bin/technologic.bc.js
$ dune build --display short bin/technologic.bc.js @install --profile release
ocamlc lib/.x.objs/byte/x__.{cmi,cmo,cmt}
ocamlc lib/.x.objs/byte/x__Y.{cmi,cmo,cmt}
Expand Down
4 changes: 2 additions & 2 deletions test/blackbox-tests/test-cases/jsoo/public-libs.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ Compilation of libraries with pulic-names
$ dune build --display short
ocamlc a/.a.objs/byte/a.{cmi,cmo,cmt}
js_of_ocaml b/.main.eobjs/jsoo/main.bc.runtime.js
js_of_ocaml .js/default/stdlib/std_exit.cmo.js
js_of_ocaml .js/default/stdlib/stdlib.cma.js
ocamlopt a/.a.objs/native/a.{cmx,o}
ocamlc b/.main.eobjs/byte/dune__exe__Main.{cmi,cmti}
ocamlc a/a.cma
js_of_ocaml .js/default/stdlib/std_exit.cmo.js
js_of_ocaml .js/default/stdlib/stdlib.cma.js
ocamlopt a/a.{a,cmxa}
ocamlc b/.main.eobjs/byte/dune__exe__Main.{cmo,cmt}
js_of_ocaml a/.a.objs/jsoo/default/a.cma.js
Expand Down
Loading