Skip to content

Commit 46dcf27

Browse files
author
Hongbo Zhang
committed
[feature] make js files relocatble
1 parent caa11c1 commit 46dcf27

File tree

371 files changed

+1585
-1262
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

371 files changed

+1585
-1262
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,4 @@ coverage
6969
dist/
7070

7171
bin/
72-
lib/
7372
man/

jscomp/build.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ cd ./test/
4040
# ./build.sh 2>> ../build.compile
4141
make $TARGET.cmj 2>> ../build.compile
4242

43-
cat $TARGET.js >> ../build.compile
43+
cat ../../lib/js/test/$TARGET.js >> ../build.compile
4444
make -j30 all 2>>../build.compile
4545
make depend 2>>../build.compile
4646
echo "<<Test finished" >> ../build.compile

jscomp/ext_filename.ml

+95-27
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,57 @@ let node_sep = "/"
3434
let node_parent = ".."
3535
let node_current = "."
3636

37+
type t =
38+
[ `File of string
39+
| `Dir of string ]
40+
41+
let cwd = lazy (Sys.getcwd ())
42+
43+
let (//) = Filename.concat
44+
45+
let combine path1 path2 =
46+
if path1 = "" then
47+
path2
48+
else if path2 = "" then path1
49+
else
50+
if Filename.is_relative path2 then
51+
path1// path2
52+
else
53+
path2
54+
55+
(* Note that [.//] is the same as [./] *)
56+
let path_as_directory x =
57+
if x = "" then x
58+
else
59+
if Ext_string.ends_with x Filename.dir_sep then
60+
x
61+
else
62+
x ^ Filename.dir_sep
63+
3764
let absolute_path s =
38-
let s = if Filename.is_relative s then Filename.concat (Sys.getcwd ()) s else s in
39-
(* Now simplify . and .. components *)
40-
let rec aux s =
41-
let base = Filename.basename s in
42-
let dir = Filename.dirname s in
43-
if dir = s then dir
44-
else if base = Filename.current_dir_name then aux dir
45-
else if base = Filename.parent_dir_name then Filename.dirname (aux dir)
46-
else Filename.concat (aux dir) base
47-
in
48-
aux s
65+
let process s =
66+
let s =
67+
if Filename.is_relative s then
68+
Lazy.force cwd // s
69+
else s in
70+
(* Now simplify . and .. components *)
71+
let rec aux s =
72+
let base,dir = Filename.basename s, Filename.dirname s in
73+
if dir = s then dir
74+
else if base = Filename.current_dir_name then aux dir
75+
else if base = Filename.parent_dir_name then Filename.dirname (aux dir)
76+
else aux dir // base
77+
in aux s in
78+
match s with
79+
| `File x -> `File (process x )
80+
| `Dir x -> `Dir (process x)
81+
4982

5083
let chop_extension ?(loc="") name =
5184
try Filename.chop_extension name
5285
with Invalid_argument _ ->
53-
invalid_arg ("Filename.chop_extension (" ^ loc ^ ":" ^ name ^ ")")
86+
Ext_pervasives.invalid_argf
87+
"Filename.chop_extension ( %s : %s )" loc name
5488

5589
let try_chop_extension s = try Filename.chop_extension s with _ -> s
5690

@@ -74,9 +108,18 @@ let try_chop_extension s = try Filename.chop_extension s with _ -> s
74108
/c/d
75109
]}
76110
*)
77-
let relative_path file1 file2 =
78-
let dir1 = Ext_string.split (Filename.dirname file1) (Filename.dir_sep.[0]) in
79-
let dir2 = Ext_string.split (Filename.dirname file2) (Filename.dir_sep.[0]) in
111+
let relative_path file_or_dir_1 file_or_dir_2 =
112+
let sep_char = Filename.dir_sep.[0] in
113+
let relevant_dir1 =
114+
(match file_or_dir_1 with
115+
| `Dir x -> x
116+
| `File file1 -> Filename.dirname file1) in
117+
let relevant_dir2 =
118+
(match file_or_dir_2 with
119+
|`Dir x -> x
120+
|`File file2 -> Filename.dirname file2 ) in
121+
let dir1 = Ext_string.split relevant_dir1 sep_char in
122+
let dir2 = Ext_string.split relevant_dir2 sep_char in
80123
let rec go (dir1 : string list) (dir2 : string list) =
81124
match dir1, dir2 with
82125
| x::xs , y :: ys when x = y
@@ -95,20 +138,29 @@ let relative_path file1 file2 =
95138

96139
let node_modules = "node_modules"
97140
let node_modules_length = String.length "node_modules"
141+
let package_json = "package.json"
142+
143+
144+
145+
98146
(** path2: a/b
99147
path1: a
100148
result: ./b
101149
TODO: [Filename.concat] with care
150+
151+
[file1] is currently compilation file
152+
[file2] is the dependency
102153
*)
103-
let node_relative_path path1 path2 =
104-
let v = Ext_string.find path2 ~sub:node_modules in
105-
let len = String.length path2 in
154+
let node_relative_path (file1 : t)
155+
(`File file2 as dep_file : [`File of string]) =
156+
let v = Ext_string.find file2 ~sub:node_modules in
157+
let len = String.length file2 in
106158
if v >= 0 then
107159
let rec skip i =
108160
if i >= len then
109-
failwith ("invalid path: " ^ path2)
161+
Ext_pervasives.failwithf "invalid path: %s" file2
110162
else
111-
match path2.[i] with
163+
match file2.[i] with
112164
| '/'
113165
| '.' -> skip (i + 1)
114166
| _ -> i
@@ -121,21 +173,22 @@ let node_relative_path path1 path2 =
121173
This seems weird though
122174
*)
123175
in
124-
Ext_string.tail_from path2
176+
Ext_string.tail_from file2
125177
(skip (v + node_modules_length))
126178
else
127-
(relative_path
128-
(try_chop_extension (absolute_path path2))
129-
(try_chop_extension (absolute_path path1))
130-
) ^ node_sep ^
131-
(try_chop_extension (Filename.basename path2))
179+
relative_path
180+
(absolute_path dep_file)
181+
(absolute_path file1)
182+
^ node_sep ^
183+
try_chop_extension (Filename.basename file2)
184+
132185

133186

134187
(** [resolve cwd module_name], [cwd] is current working directory, absolute path
135188
*)
136189
let resolve ~cwd module_name =
137190
let rec aux origin cwd module_name =
138-
let v = Filename.concat (Filename.concat cwd node_modules) module_name
191+
let v = ( cwd // node_modules) // module_name
139192
in
140193
if Sys.is_directory v then v
141194
else
@@ -145,3 +198,18 @@ let resolve ~cwd module_name =
145198
else Ext_pervasives.failwithf "%s not found in %s" module_name origin
146199
in
147200
aux cwd cwd module_name
201+
202+
203+
let resolve_package cwd =
204+
let rec aux cwd =
205+
if Sys.file_exists (cwd // package_json) then cwd
206+
else
207+
let cwd' = Filename.dirname cwd in
208+
if String.length cwd' < String.length cwd then
209+
aux cwd'
210+
else
211+
Ext_pervasives.failwithf "package.json not found from %s" cwd
212+
in
213+
aux cwd
214+
215+
let package_dir = lazy (resolve_package (Lazy.force cwd))

jscomp/ext_filename.mli

+15-4
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,17 @@
2626

2727

2828

29+
(* TODO:
30+
Change the module name, this code is not really an extension of the standard
31+
library but rather specific to JS Module name convention.
32+
*)
2933

34+
type t =
35+
[ `File of string
36+
| `Dir of string ]
3037

38+
val combine : string -> string -> string
39+
val path_as_directory : string -> string
3140

3241
(** An extension module to calculate relative path follow node/npm style.
3342
TODO : this short name will have to change upon renaming the file.
@@ -41,12 +50,14 @@
4150
just treat it as a library instead
4251
*)
4352

44-
val node_relative_path : string -> string -> string
45-
(** TODO Change the module name, this code is not really an extension of the standard
46-
library but rather specific to JS Module name convention.
47-
*)
53+
val node_relative_path : t -> [`File of string] -> string
4854

4955
val chop_extension : ?loc:string -> string -> string
5056

5157

5258
val resolve : cwd:string -> string -> string
59+
60+
val resolve_package : string -> string
61+
62+
val cwd : string Lazy.t
63+
val package_dir : string Lazy.t

jscomp/ext_pervasives.ml

+2
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,5 @@ let is_pos_pow n =
6262
try aux 0 n with M.E -> -1
6363

6464
let failwithf fmt = Format.ksprintf failwith fmt
65+
66+
let invalid_argf fmt = Format.ksprintf invalid_arg fmt

jscomp/ext_pervasives.mli

+2
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,5 @@ val with_file_as_pp : string -> (Format.formatter -> 'a) -> 'a
4242
val is_pos_pow : Int32.t -> int
4343

4444
val failwithf : ('a, unit, string, 'b) format4 -> 'a
45+
46+
val invalid_argf : ('a, unit, string, 'b) format4 -> 'a

jscomp/js_cmj_format.ml

+3-3
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ let from_file name : t =
7171
let ic = open_in_bin name in
7272
let buffer = really_input_string ic cmj_magic_number_length in
7373
if buffer <> cmj_magic_number then
74-
failwith
75-
("cmj files have incompatible versions, please rebuilt using the new compiler : "
76-
^ __LOC__)
74+
Ext_pervasives.failwithf
75+
"cmj files have incompatible versions, please rebuilt using the new compiler : %s"
76+
__LOC__
7777
else
7878
let v : t = input_value ic in
7979
close_in ic ;

jscomp/js_config.ml

+32-4
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,36 @@ let get_goog_package_name () =
7474
| AmdJS
7575
| NodeJS -> None
7676

77-
let get_npm_package_path () = None
78-
77+
let npm_package_path = ref None
78+
let set_npm_package_path s = npm_package_path := Some s
79+
let get_npm_package_path () = !npm_package_path
80+
81+
let (//) = Filename.concat
82+
(* for a single pass compilation, [output_dir]
83+
can be cached
84+
*)
85+
let get_output_dir filename =
86+
match get_npm_package_path () with
87+
| None ->
88+
if Filename.is_relative filename then
89+
Lazy.force Ext_filename.cwd //
90+
Filename.dirname filename
91+
else
92+
Filename.dirname filename
93+
| Some x ->
94+
Lazy.force Ext_filename.package_dir // x
95+
96+
97+
98+
(* Note that we can have different [basename] when passed
99+
to many files
100+
*)
101+
let get_output_file filename =
102+
let basename = Filename.basename filename in
103+
Filename.concat (get_output_dir filename)
104+
(Ext_filename.chop_extension ~loc:__LOC__ basename ^ get_ext())
105+
106+
79107
let default_gen_tds = ref false
80108

81109
let stdlib_set = String_set.of_list [
@@ -88,10 +116,10 @@ let stdlib_set = String_set.of_list [
88116
"arrayLabels";
89117
"hashtbl";
90118
"queue";
91-
"buffer";
119+
"buffer";
92120
"int32";
93121
"random";
94-
"bytes";
122+
"bytes";
95123
"int64";
96124
"scanf";
97125
"bytesLabels";

jscomp/js_config.mli

+4
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ type env =
3636
val get_env : unit -> env
3737
val get_ext : unit -> string
3838

39+
val get_output_dir : string -> string
40+
val get_output_file : string -> string
3941
val get_goog_package_name : unit -> string option
42+
43+
val set_npm_package_path : string -> unit
4044
val get_npm_package_path : unit -> string option
4145

4246
val set_env : env -> unit

jscomp/js_main.ml

+7-27
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,10 @@ let process_file ppf name =
3434
Js_implementation.interface ppf name opref;
3535
if !make_package then objfiles := (opref ^ ".cmi") :: !objfiles
3636
end
37-
(* else if Filename.check_suffix name ".cmo" *)
38-
(* || Filename.check_suffix name ".cma" then *)
39-
(* objfiles := name :: !objfiles *)
40-
(* else if Filename.check_suffix name ".cmi" && !make_package then *)
41-
(* objfiles := name :: !objfiles *)
42-
(* else if Filename.check_suffix name ext_obj *)
43-
(* || Filename.check_suffix name ext_lib then *)
44-
(* ccobjs := name :: !ccobjs *)
45-
(* else if Filename.check_suffix name ext_dll then *)
46-
(* dllibs := name :: !dllibs *)
47-
(* else if Filename.check_suffix name ".c" then begin *)
48-
(* Compile.c_file name; *)
49-
(* ccobjs := (Filename.chop_suffix (Filename.basename name) ".c" ^ ext_obj) *)
50-
(* :: !ccobjs *)
51-
(* end *)
5237
else
5338
raise(Arg.Bad("don't know what to do with " ^ name))
5439

55-
let usage = "Usage: ocamlc <options> <files>\nOptions are:"
40+
let usage = "Usage: bsc <options> <files>\nOptions are:"
5641

5742
let ppf = Format.err_formatter
5843

@@ -145,10 +130,15 @@ module Options = Main_args.Make_bytecomp_options (struct
145130
end)
146131

147132
let add_include_path s =
148-
let path = Ext_filename.resolve (Sys.getcwd ()) s in
133+
let path =
134+
Ext_filename.resolve
135+
(Lazy.force Ext_filename.cwd) s in
149136
Clflags.include_dirs := path :: ! Clflags.include_dirs
150137

151138
let buckle_script_flags =
139+
("-js-npm-output-path", Arg.String Js_config.set_npm_package_path,
140+
" set npm-output-path, for example `lib/js`")
141+
::
152142
("-npm-package", Arg.String add_include_path,
153143
" set package names, for example bs-platform " )
154144
:: ("-js-module", Arg.String Js_config.cmd_set_module,
@@ -165,16 +155,6 @@ let main () =
165155
try
166156
readenv ppf Before_args;
167157
Arg.parse buckle_script_flags anonymous usage;
168-
readenv ppf Before_link;
169-
if
170-
List.length (List.filter (fun x -> !x)
171-
[make_archive;make_package;compile_only;output_c_object])
172-
> 1
173-
then
174-
if !print_types then
175-
fatal "Option -i is incompatible with -pack, -a, -output-obj"
176-
else
177-
fatal "Please specify at most one of -pack, -a, -c, -output-obj";
178158
exit 0
179159
with x ->
180160
Location.report_exception ppf x;

0 commit comments

Comments
 (0)