Skip to content

part 2: support external-stdlib config #4925

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

Merged
merged 3 commits into from
Jan 30, 2021
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
4 changes: 4 additions & 0 deletions docs/docson/build-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,10 @@
"type": "boolean",
"description": "(Experimental) whether to use the OCaml standard library. Default: true"
},
"external-stdlib" : {
"type" : "string",
"description": "Use the external stdlib library instead of the one shipped with the compiler package"
},
"bs-external-includes": {
"type": "array",
"items": {
Expand Down
1 change: 1 addition & 0 deletions jscomp/bsb/bsb_build_schemas.ml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ let export_none = "none"


let use_stdlib = "use-stdlib"
let external_stdlib = "external-stdlib"
let reason = "reason"
let react_jsx = "react-jsx"

Expand Down
64 changes: 21 additions & 43 deletions jscomp/bsb/bsb_config_parse.ml
Original file line number Diff line number Diff line change
Expand Up @@ -90,48 +90,26 @@ let extract_package_name_and_namespace
- the running bsb and vendoring bsb is the same
- the running bsb need delete stale build artifacts
(kinda check npm upgrade)
*)
let check_version_exit (map : json_map) stdlib_path =
match Map_string.find_exn map Bsb_build_schemas.version with
| Str {str } ->
if str <> Bs_version.version then
begin
Format.fprintf Format.err_formatter
"@{<error>bs-platform version mismatch@} Running bsb @{<info>%s@} (%s) vs vendored @{<info>%s@} (%s)@."
Bs_version.version
(Filename.dirname (Filename.dirname Sys.executable_name))
str
stdlib_path
;
exit 2
end
| _ -> assert false

let check_stdlib (map : json_map) cwd (*built_in_package*) =

Note if the setup is correct:
the running compiler and node_modules/bs-platform
should be the same version,
The exact check is that the running compiler should have a
compatible runtime version installed, the location of the
compiler is actually not relevant.
We disable the check temporarily
e.g,
```
bsc -runtime runtime_dir@version
```
*)
let check_stdlib (map : json_map) (*built_in_package*) : bool =
match map.?( Bsb_build_schemas.use_stdlib) with
| Some (False _) -> None
| Some (False _) -> false
| None
| Some _ ->
begin
let current_package : Bsb_pkg_types.t = Global !Bs_version.package_name in
if Sys.getenv_opt "RES_SKIP_STDLIB_CHECK" = None then begin
let stdlib_path =
Bsb_pkg.resolve_bs_package ~cwd current_package in
let json_spec =
Ext_json_parse.parse_json_from_file
(* No exn raised: stdlib has package.json *)
(Filename.concat stdlib_path Literals.package_json) in
match json_spec with
| Obj {map} ->
check_version_exit map stdlib_path;

| _ -> assert false
end;
Some {
Bsb_config_types.package_name = current_package;
package_install_path = Filename.dirname Bsb_global_paths.bsc_dir // Bsb_config.lib_ocaml;
}
end
| Some _ ->
true




Expand Down Expand Up @@ -355,7 +333,7 @@ let interpret_json
array from the bsconfig and set the backend_ref to the first entry, if any. *)

(* The default situation is empty *)
let built_in_package = check_stdlib map per_proj_dir in
let built_in_package : bool = check_stdlib map in

let pp_flags : string option =
extract_string map Bsb_build_schemas.pp_flags (fun p ->
Expand Down Expand Up @@ -410,7 +388,7 @@ let interpret_json
js_post_build_cmd = (extract_js_post_build map per_proj_dir);
package_specs =
(match package_kind with
| Toplevel -> Bsb_package_specs.from_map map
| Toplevel -> Bsb_package_specs.from_map ~cwd:per_proj_dir map
| Pinned_dependency x
| Dependency x -> x);
file_groups = groups;
Expand All @@ -434,7 +412,7 @@ let package_specs_from_bsconfig () =
let json = Ext_json_parse.parse_json_from_file Literals.bsconfig_json in
begin match json with
| Obj {map} ->
Bsb_package_specs.from_map map,
Bsb_package_specs.from_map ~cwd:Bsb_global_paths.cwd map,
extract_pinned_dependencies map
| _ -> assert false
end
2 changes: 1 addition & 1 deletion jscomp/bsb/bsb_config_types.ml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ type t =
bs_dependencies : dependencies;
bs_dev_dependencies : dependencies;
pinned_dependencies : Set_string.t;
built_in_dependency : dependency option;
built_in_dependency : bool;
warning : Bsb_warning.t;
(*TODO: maybe we should always resolve bs-platform
so that we can calculate correct relative path in
Expand Down
12 changes: 7 additions & 5 deletions jscomp/bsb/bsb_merlin_gen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,13 @@ let merlin_file_gen ~per_proj_dir:(per_proj_dir:string)
Buffer.add_string buffer merlin_b;
Buffer.add_string buffer path ;
);
Ext_option.iter built_in_dependency (fun package ->
let path = package.package_install_path in
Buffer.add_string buffer (merlin_s ^ path );
Buffer.add_string buffer (merlin_b ^ path)
);
if built_in_dependency then (
let path =
(Filename.dirname Bsb_global_paths.bsc_dir)
// "lib" //"ocaml" in
Buffer.add_string buffer (merlin_s ^ path );
Buffer.add_string buffer (merlin_b ^ path)
);
let bsc_string_flag = bsc_flg_to_merlin_ocamlc_flg bsc_flags in
Buffer.add_string buffer bsc_string_flag ;
Buffer.add_string buffer (warning_to_merlin_flg warning);
Expand Down
2 changes: 1 addition & 1 deletion jscomp/bsb/bsb_ninja_gen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ let output_ninja_and_namespace_map
~gentype_config
~has_postbuild:js_post_build_cmd
~pp_file
~has_builtin:(built_in_dependency <> None)
~has_builtin:built_in_dependency
~reason_react_jsx
~package_specs
~namespace
Expand Down
3 changes: 2 additions & 1 deletion jscomp/bsb/bsb_ninja_rule.ml
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ let make_custom_rules
if read_cmi <> `is_cmi then begin
Ext_buffer.add_string buf " -bs-package-name ";
Ext_buffer.add_string buf package_name;
Ext_buffer.add_string buf (Bsb_package_specs.package_flag_of_package_specs package_specs "$in_d")
Ext_buffer.add_string buf
(Bsb_package_specs.package_flag_of_package_specs package_specs ~dirname:"$in_d")
end;
begin match bs_dependencies, bs_dev_dependencies with
| [], [] -> ()
Expand Down
58 changes: 38 additions & 20 deletions jscomp/bsb/bsb_package_specs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,18 @@ type spec = {
suffix : Ext_js_suffix.t
}

(*FIXME: use assoc list instead *)
module Spec_set = Set.Make( struct type t = spec
let compare = Pervasives.compare
end)

type t = Spec_set.t
type t = {
modules : Spec_set.t;
runtime: string option;
(* This has to be resolved as early as possible, since
the path will be inherited in sub projects
*)
}

let (.?()) = Map_string.find_opt

Expand Down Expand Up @@ -89,8 +96,8 @@ and from_json_single suffix (x : Ext_json_types.t) : spec =
| Str {str = format; loc } ->
{format = supported_format format loc ; in_source = false ; suffix }
| Obj {map; loc} ->
begin match Map_string.find_exn map "module" with
| Str {str = format} ->
begin match map .?("module") with
| Some(Str {str = format}) ->
let in_source =
match map.?(Bsb_build_schemas.in_source) with
| Some (True _) -> true
Expand All @@ -108,13 +115,10 @@ and from_json_single suffix (x : Ext_json_types.t) : spec =
Bsb_exception.errorf ~loc:(Ext_json.loc_of x) "expect a string field"
| None -> suffix in
{format = supported_format format loc ; in_source ; suffix}
| Arr _ ->
Bsb_exception.errorf ~loc
"package-specs: when the configuration is an object, `module` field should be a string, not an array. If you want to pass multiple module specs, try turning package-specs into an array of objects (or strings) instead."
| _ ->
| Some _ ->
Bsb_exception.errorf ~loc
"package-specs: the `module` field of the configuration object should be a string."
| exception _ ->
"package-specs: when the configuration is an object, `module` field should be a string, not an array. If you want to pass multiple module specs, try turning package-specs into an array of objects (or strings) instead."
| None ->
Bsb_exception.errorf ~loc
"package-specs: when the configuration is an object, the `module` field is mandatory."
end
Expand Down Expand Up @@ -144,12 +148,16 @@ let package_flag ({format; in_source; suffix } : spec) dir =
(Ext_js_suffix.to_string suffix)
)

(* FIXME: we should adapt it *)
let package_flag_of_package_specs (package_specs : t)
(dirname : string ) : string =
Spec_set.fold (fun format acc ->
~(dirname : string ) : string =
let res = Spec_set.fold (fun format acc ->
Ext_string.inter2 acc (package_flag format dirname )
) package_specs Ext_string.empty

) package_specs.modules Ext_string.empty in
match package_specs.runtime with
| None -> res
| Some x ->
res ^ " -runtime " ^ x
let default_package_specs suffix =
Spec_set.singleton
{ format = NodeJS ; in_source = false; suffix }
Expand All @@ -161,7 +169,7 @@ let default_package_specs suffix =

*)
let get_list_of_output_js
(package_specs : Spec_set.t)
(package_specs : t)
(output_file_sans_extension : string)
=
Spec_set.fold
Expand All @@ -174,17 +182,17 @@ let get_list_of_output_js
(if spec.in_source then Bsb_config.rev_lib_bs_prefix basename
else Bsb_config.lib_bs_prefix_of_format spec.format // basename)
:: acc
) package_specs []
) package_specs.modules []


let list_dirs_by
(package_specs : Spec_set.t)
(package_specs : t)
(f : string -> unit)
=
Spec_set.iter (fun (spec : spec) ->
if not spec.in_source then
f (Bsb_config.top_prefix_of_format spec.format)
) package_specs
) package_specs.modules

type json_map = Ext_json_types.t Map_string.t

Expand All @@ -201,10 +209,20 @@ let extract_bs_suffix_exn (map : json_map) : Ext_js_suffix.t =
Bsb_exception.config_error config
"expect a string exteion like \".js\" here"

let from_map map =
let from_map ~(cwd:string) map =
let suffix = extract_bs_suffix_exn map in
match map.?(Bsb_build_schemas.package_specs) with
let modules = match map.?(Bsb_build_schemas.package_specs) with
| Some x ->
from_json suffix x
| None -> default_package_specs suffix
| None -> default_package_specs suffix in
let runtime =
match map.?(Bsb_build_schemas.external_stdlib) with
| None -> None
| Some(Str{str; _}) ->
Some (Bsb_pkg.resolve_bs_package ~cwd (Bsb_pkg_types.string_as_package str))
| _ -> assert false in
{
runtime;
modules
}

6 changes: 5 additions & 1 deletion jscomp/bsb/bsb_package_specs.mli
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type t


val from_map:
cwd:string ->
Ext_json_types.t Map_string.t -> t

val get_list_of_output_js :
Expand All @@ -39,8 +40,11 @@ val get_list_of_output_js :
Sample output: {[ -bs-package-output commonjs:lib/js/jscomp/test]}
*)
val package_flag_of_package_specs :
t -> string -> string
t ->
dirname:string ->
string

(* used to ensure each dir does exist *)
val list_dirs_by :
t ->
(string -> unit) ->
Expand Down
1 change: 1 addition & 0 deletions jscomp/bsb/bsb_pkg.mli
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ val resolve_bs_package :
cwd:string -> Bsb_pkg_types.t -> string


(** used by watcher *)
val to_list:
(Bsb_pkg_types.t ->
string ->
Expand Down
5 changes: 4 additions & 1 deletion jscomp/bsb/bsb_pkg_types.ml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ let string_as_package (s : string) : t =
if v = '@' then
let scope_id =
Ext_string.no_slash_idx s in
assert (scope_id > 0);
assert (scope_id > 0);
(* better-eror message for invalid scope package:
@rescript/std
*)
Scope(
String.sub s (scope_id + 1) (len - scope_id - 1),
String.sub s 0 scope_id
Expand Down
1 change: 1 addition & 0 deletions jscomp/common/js_config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,4 @@ let as_ppx = ref false

let mono_empty_array = ref true

let customize_runtime = ref None
1 change: 1 addition & 0 deletions jscomp/common/js_config.mli
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,4 @@ val no_export: bool ref
val as_ppx : bool ref

val mono_empty_array : bool ref
val customize_runtime : string option ref
10 changes: 9 additions & 1 deletion jscomp/core/js_name_of_module_id.ml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ let get_runtime_module_path
(*Invariant: the package path to bs-platform, it is used to
calculate relative js path
*)
((Filename.dirname (Filename.dirname Sys.executable_name)) // dep_path // js_file)
(match !Js_config.customize_runtime with
| None ->
((Filename.dirname (Filename.dirname Sys.executable_name)) // dep_path // js_file)
| Some path ->
path //dep_path // js_file
)



Expand Down Expand Up @@ -142,6 +147,9 @@ let string_of_module_id
which is guaranteed by [-bs-package-output]
*)
else
if Js_packages_info.is_runtime_package dep_package_info then
get_runtime_module_path dep_module_id current_package_info module_system
else
begin match module_system with
| NodeJS | Es6 ->
dep_pkg.pkg_rel_path // js_file
Expand Down
14 changes: 13 additions & 1 deletion jscomp/core/js_packages_info.ml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,19 @@ let runtime_test_package_specs : t = {
name = Pkg_runtime;
module_systems = []
}
let same_package_by_name (x : t) (y : t) = x.name = y.name

let same_package_by_name (x : t) (y : t) =
match x.name with
| Pkg_empty ->
y.name = Pkg_empty
| Pkg_runtime ->
y.name = Pkg_runtime
| Pkg_normal s ->
begin match y.name with
| Pkg_normal y -> s = y
| Pkg_empty | Pkg_runtime -> false
end


let is_runtime_package (x : t) =
x.name = Pkg_runtime
Expand Down
Loading