Skip to content

Commit 4d10995

Browse files
authored
Support getting paths from -libloc flags (#2482)
* Make [Load_path.Dir] store full paths * Add arguments * Reading libloc * Change format to '-libloc path:libs:hidden_libs' and allow multiple flags * Fix splitting library names * Fix typo * Fix closing of libloc file * .depend and makefile fixes * Review changes
1 parent 6b748bc commit 4d10995

File tree

14 files changed

+136
-27
lines changed

14 files changed

+136
-27
lines changed

ocaml/.depend

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,13 @@ utils/load_path.cmo : \
180180
utils/misc.cmi \
181181
utils/local_store.cmi \
182182
utils/config.cmi \
183+
utils/clflags.cmi \
183184
utils/load_path.cmi
184185
utils/load_path.cmx : \
185186
utils/misc.cmx \
186187
utils/local_store.cmx \
187188
utils/config.cmx \
189+
utils/clflags.cmx \
188190
utils/load_path.cmi
189191
utils/load_path.cmi :
190192
utils/local_store.cmo : \

ocaml/Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,13 +1466,13 @@ tools/ocamldep$(EXE): OC_BYTECODE_LINKFLAGS += -compat-32
14661466
ocamlprof_LIBRARIES =
14671467
ocamlprof_MODULES = \
14681468
config build_path_prefix_map misc identifiable numbers arg_helper \
1469-
local_store load_path zero_alloc_annotations clflags terminfo warnings \
1469+
local_store zero_alloc_annotations clflags load_path terminfo warnings \
14701470
location longident docstrings syntaxerr ast_helper camlinternalMenhirLib \
14711471
parser pprintast lexer parse ocamlprof
14721472

14731473
ocamlcp_ocamloptp_MODULES = \
14741474
config build_path_prefix_map misc profile warnings identifiable numbers \
1475-
arg_helper local_store load_path zero_alloc_annotations clflags terminfo \
1475+
arg_helper local_store zero_alloc_annotations clflags load_path terminfo \
14761476
location ccomp compenv main_args ocamlcp_common zero_alloc_annotations
14771477

14781478
ocamlcp_LIBRARIES =
@@ -1490,7 +1490,7 @@ ocamlmklib_MODULES = config build_path_prefix_map misc ocamlmklib
14901490
ocamlmktop_LIBRARIES =
14911491
ocamlmktop_MODULES = \
14921492
config build_path_prefix_map misc identifiable numbers arg_helper \
1493-
local_store load_path zero_alloc_annotations clflags profile ccomp ocamlmktop
1493+
local_store zero_alloc_annotations clflags load_path profile ccomp ocamlmktop
14941494

14951495
# Reading cmt files
14961496

ocaml/compilerlibs/Makefile.compilerlibs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ UTILS = \
3333
utils/numbers.cmo \
3434
utils/arg_helper.cmo \
3535
utils/local_store.cmo \
36-
utils/load_path.cmo \
3736
utils/zero_alloc_annotations.cmo \
3837
utils/clflags.cmo \
38+
utils/load_path.cmo \
3939
utils/debug.cmo \
4040
utils/language_extension_kernel.cmo \
4141
utils/language_extension.cmo \

ocaml/driver/main_args.ml

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,20 @@ let mk_H f =
165165
"<dir> Add <dir> to the list of \"hidden\" include directories\n\
166166
\ (Like -I, but the program can not directly reference these dependencies)"
167167

168+
let mk_libloc f =
169+
"-libloc", Arg.String f, "<dir>:<libs>:<hidden_libs> Add .libloc directory configuration.\n\
170+
\ .libloc directory is alternative (to -I and -H flags) way of telling\n\
171+
\ compiler where to find files. Each `.libloc` directory should have a\n\
172+
\ structure of `.libloc/<lib>/cmi-cmx`, where `<lib>` is a library name\n\
173+
\ and `cmi-cmx` is a file where each line is of format `<filename> <path>`\n\
174+
\ telling compiler that <filename> for library <lib> is accessible\n\
175+
\ at <path>. If <path> is relative, then it is relative to a parent directory\n\
176+
\ of a `.libloc` directory.\n\
177+
\ <libs> and <hidden_libs> are comma-separated lists of libraries, to let\n\
178+
\ compiler know which libraries should be accessible via this `.libloc`\n\
179+
\ directory. Difference between <libs> and <hidden_libs> is the same as\n\
180+
\ the difference between -I and -H flags"
181+
168182
let mk_impl f =
169183
"-impl", Arg.String f, "<file> Compile <file> as a .ml file"
170184

@@ -880,6 +894,7 @@ module type Common_options = sig
880894
val _alert : string -> unit
881895
val _I : string -> unit
882896
val _H : string -> unit
897+
val _libloc : string -> unit
883898
val _labels : unit -> unit
884899
val _alias_deps : unit -> unit
885900
val _no_alias_deps : unit -> unit
@@ -1175,6 +1190,7 @@ struct
11751190
mk_i F._i;
11761191
mk_I F._I;
11771192
mk_H F._H;
1193+
mk_libloc F._libloc;
11781194
mk_impl F._impl;
11791195
mk_intf F._intf;
11801196
mk_intf_suffix F._intf_suffix;
@@ -1279,6 +1295,7 @@ struct
12791295
mk_alert F._alert;
12801296
mk_I F._I;
12811297
mk_H F._H;
1298+
mk_libloc F._libloc;
12821299
mk_init F._init;
12831300
mk_labels F._labels;
12841301
mk_alias_deps F._alias_deps;
@@ -1393,6 +1410,7 @@ struct
13931410
mk_i F._i;
13941411
mk_I F._I;
13951412
mk_H F._H;
1413+
mk_libloc F._libloc;
13961414
mk_impl F._impl;
13971415
mk_inline F._inline;
13981416
mk_inline_toplevel F._inline_toplevel;
@@ -1538,6 +1556,7 @@ module Make_opttop_options (F : Opttop_options) = struct
15381556
mk_compact F._compact;
15391557
mk_I F._I;
15401558
mk_H F._H;
1559+
mk_libloc F._libloc;
15411560
mk_init F._init;
15421561
mk_inline F._inline;
15431562
mk_inline_toplevel F._inline_toplevel;
@@ -1654,6 +1673,7 @@ struct
16541673
mk_alert F._alert;
16551674
mk_I F._I;
16561675
mk_H F._H;
1676+
mk_libloc F._libloc;
16571677
mk_impl F._impl;
16581678
mk_intf F._intf;
16591679
mk_intf_suffix F._intf_suffix;
@@ -1763,7 +1783,7 @@ module Default = struct
17631783
let _no_absname = clear Clflags.absname
17641784
let _no_alias_deps = set transparent_modules
17651785
let _no_app_funct = clear applicative_functors
1766-
let _directory d = Clflags.directory := Some d
1786+
let _directory d = Clflags.directory := Some d
17671787
let _no_principal = clear principal
17681788
let _no_rectypes = clear recursive_types
17691789
let _no_strict_formats = clear strict_formats
@@ -1806,6 +1826,18 @@ module Default = struct
18061826
include Common
18071827
let _I dir = include_dirs := dir :: (!include_dirs)
18081828
let _H dir = hidden_include_dirs := dir :: (!hidden_include_dirs)
1829+
let _libloc s =
1830+
match String.split_on_char ':' s with
1831+
| [ path; libs; hidden_libs ] ->
1832+
let split libs =
1833+
match libs |> String.split_on_char ',' with
1834+
| [ "" ] -> []
1835+
| libs -> libs
1836+
in
1837+
let libs = split libs in
1838+
let hidden_libs = split hidden_libs in
1839+
libloc := { Libloc.path; libs; hidden_libs } :: !libloc
1840+
| _ -> Compenv.fatal "Incorrect -libloc format, expected: <path>:<lib1>,<lib2>,...:<hidden_lib1>,<hidden_lib2>,..."
18091841
let _color = Misc.set_or_ignore color_reader.parse color
18101842
let _dlambda = set dump_lambda
18111843
let _dparsetree = set dump_parsetree
@@ -2061,6 +2093,7 @@ module Default = struct
20612093
Odoc_global.hidden_include_dirs :=
20622094
(s :: (!Odoc_global.hidden_include_dirs))
20632095
*) ()
2096+
let _libloc(_:string) = ()
20642097
let _impl (_:string) =
20652098
(* placeholder:
20662099
Odoc_global.files := ((!Odoc_global.files) @ [Odoc_global.Impl_file s])

ocaml/driver/main_args.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module type Common_options = sig
2222
val _alert : string -> unit
2323
val _I : string -> unit
2424
val _H : string -> unit
25+
val _libloc : string -> unit
2526
val _labels : unit -> unit
2627
val _alias_deps : unit -> unit
2728
val _no_alias_deps : unit -> unit

ocaml/otherlibs/dynlink/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ COMPILERLIBS_SOURCES=\
8383
utils/numbers.ml \
8484
utils/arg_helper.ml \
8585
utils/local_store.ml \
86+
utils/clflags.ml \
8687
utils/load_path.ml \
8788
utils/zero_alloc_annotations.ml \
88-
utils/clflags.ml \
8989
utils/debug.ml \
9090
utils/language_extension_kernel.ml \
9191
utils/language_extension.ml \

ocaml/tools/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ opt.opt: profiling.cmx
102102
OCAMLCP = config.cmo build_path_prefix_map.cmo misc.cmo profile.cmo \
103103
warnings.cmo identifiable.cmo numbers.cmo arg_helper.cmo \
104104
language_extension_kernel.cmo language_extension.cmo \
105-
zero_alloc_annotations.cmo clflags.cmo local_store.cmo \
106-
terminfo.cmo location.cmo load_path.cmo ccomp.cmo compenv.cmo \
105+
zero_alloc_annotations.cmo local_store.cmo \
106+
terminfo.cmo location.cmo clflags.cmo load_path.cmo ccomp.cmo compenv.cmo \
107107
main_args.cmo
108108

109109
ocamlcp$(EXE): $(OCAMLCP) ocamlcp.cmo

ocaml/typing/env.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2669,7 +2669,7 @@ let unit_name_of_filename fn =
26692669
| _ -> None
26702670

26712671
let persistent_structures_of_dir dir =
2672-
Load_path.Dir.files dir
2672+
Load_path.Dir.basenames dir
26732673
|> List.to_seq
26742674
|> Seq.filter_map unit_name_of_filename
26752675
|> String.Set.of_seq

ocaml/utils/clflags.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,19 @@ and dllibs = ref ([] : string list) (* .so and -dllib -lxxx *)
4444

4545
let cmi_file = ref None
4646

47+
module Libloc = struct
48+
type t = {
49+
path: string;
50+
libs: string list;
51+
hidden_libs: string list
52+
}
53+
end
54+
4755
let compile_only = ref false (* -c *)
4856
and output_name = ref (None : string option) (* -o *)
4957
and include_dirs = ref ([] : string list) (* -I *)
5058
and hidden_include_dirs = ref ([] : string list) (* -H *)
59+
and libloc = ref ([] : Libloc.t list) (* -libloc *)
5160
and no_std_include = ref false (* -nostdlib *)
5261
and no_cwd = ref false (* -nocwd *)
5362
and print_types = ref false (* -i *)

ocaml/utils/clflags.mli

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ val set_int_arg :
5151
val set_float_arg :
5252
int option -> Float_arg_helper.parsed ref -> float -> float option -> unit
5353

54+
module Libloc : sig
55+
type t = {
56+
path: string;
57+
libs: string list;
58+
hidden_libs: string list
59+
}
60+
end
61+
5462
val objfiles : string list ref
5563
val ccobjs : string list ref
5664
val dllibs : string list ref
@@ -59,6 +67,7 @@ val compile_only : bool ref
5967
val output_name : string option ref
6068
val include_dirs : string list ref
6169
val hidden_include_dirs : string list ref
70+
val libloc : Libloc.t list ref
6271
val no_std_include : bool ref
6372
val no_cwd : bool ref
6473
val print_types : bool ref

ocaml/utils/load_path.ml

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,52 @@
1515
open Local_store
1616

1717
module Dir : sig
18+
type entry = {
19+
basename : string;
20+
path : string
21+
}
22+
1823
type t
1924

2025
val path : t -> string
21-
val files : t -> string list
26+
val files : t -> entry list
27+
val basenames : t -> string list
2228
val hidden : t -> bool
2329

2430
val create : hidden:bool -> string -> t
31+
val create_libloc : hidden:bool -> libloc:string -> string -> t
2532

2633
val find : t -> string -> string option
2734
val find_uncap : t -> string -> string option
2835
end = struct
36+
type entry = {
37+
basename : string;
38+
path : string
39+
}
40+
2941
type t = {
3042
path : string;
31-
files : string list;
32-
hidden : bool;
43+
files : entry list;
44+
hidden : bool
3345
}
3446

3547
let path t = t.path
3648
let files t = t.files
49+
let basenames t = List.map (fun { basename; _ } -> basename) t.files
3750
let hidden t = t.hidden
3851

3952
let find t fn =
40-
if List.mem fn t.files then
41-
Some (Filename.concat t.path fn)
42-
else
43-
None
53+
List.find_map (fun { basename; path } ->
54+
if String.equal basename fn then
55+
Some path
56+
else
57+
None) t.files
4458

4559
let find_uncap t fn =
4660
let fn = String.uncapitalize_ascii fn in
47-
let search base =
48-
if String.uncapitalize_ascii base = fn then
49-
Some (Filename.concat t.path base)
61+
let search { basename; path } =
62+
if String.uncapitalize_ascii basename = fn then
63+
Some path
5064
else
5165
None
5266
in
@@ -62,7 +76,36 @@ end = struct
6276
[||]
6377

6478
let create ~hidden path =
65-
{ path; files = Array.to_list (readdir_compat path); hidden }
79+
let files = Array.to_list (readdir_compat path)
80+
|> List.map (fun basename -> { basename; path = Filename.concat path basename }) in
81+
{ path; files; hidden }
82+
83+
let read_libloc_file path =
84+
let ic = open_in path in
85+
Misc.try_finally
86+
(fun () ->
87+
let rec loop acc =
88+
try
89+
let line = input_line ic in
90+
let (basename, path) = Misc.Stdlib.String.split_first_exn ~split_on:' ' line in
91+
loop ({ basename; path } :: acc)
92+
with End_of_file -> acc
93+
in
94+
loop [])
95+
~always:(fun () -> close_in ic)
96+
97+
let create_libloc ~hidden ~libloc libname =
98+
let libloc_lib_path = Filename.concat libloc libname in
99+
let files = read_libloc_file (Filename.concat libloc_lib_path "cmi-cmx") in
100+
let files = List.map (fun { basename; path } ->
101+
let path = if Filename.is_relative path then
102+
(* Paths are relative to parent directory of libloc directory *)
103+
Filename.concat (Filename.dirname libloc) path
104+
else
105+
path
106+
in
107+
{ basename; path }) files in
108+
{ path = libloc_lib_path; files; hidden }
66109
end
67110

68111
type visibility = Visible | Hidden
@@ -103,8 +146,7 @@ end = struct
103146
STbl.clear !visible_files_uncap
104147

105148
let prepend_add dir =
106-
List.iter (fun base ->
107-
let fn = Filename.concat (Dir.path dir) base in
149+
List.iter (fun ({ basename = base; path = fn } : Dir.entry) ->
108150
if Dir.hidden dir then begin
109151
STbl.replace !hidden_files base fn;
110152
STbl.replace !hidden_files_uncap (String.uncapitalize_ascii base) fn
@@ -122,8 +164,7 @@ end = struct
122164
STbl.replace !visible_files base fn
123165
in
124166
List.iter
125-
(fun base ->
126-
let fn = Filename.concat (Dir.path dir) base in
167+
(fun ({ basename = base; path = fn }: Dir.entry) ->
127168
update base fn visible_files hidden_files;
128169
let ubase = String.uncapitalize_ascii base in
129170
update ubase fn visible_files_uncap hidden_files_uncap)
@@ -175,6 +216,10 @@ let init ~auto_include ~visible ~hidden =
175216
reset ();
176217
visible_dirs := List.rev_map (Dir.create ~hidden:false) visible;
177218
hidden_dirs := List.rev_map (Dir.create ~hidden:true) hidden;
219+
List.iter (fun (libloc : Clflags.Libloc.t) ->
220+
visible_dirs := Misc.rev_map_end (fun lib -> Dir.create_libloc ~hidden:false ~libloc:libloc.path lib) libloc.libs !visible_dirs;
221+
hidden_dirs := Misc.rev_map_end (fun lib -> Dir.create_libloc ~hidden:true ~libloc:libloc.path lib) libloc.hidden_libs !hidden_dirs
222+
) !Clflags.libloc;
178223
List.iter Path_cache.prepend_add !hidden_dirs;
179224
List.iter Path_cache.prepend_add !visible_dirs;
180225
auto_include_callback := auto_include

ocaml/utils/load_path.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ module Dir : sig
3737

3838
val create : hidden:bool -> string -> t
3939

40-
val files : t -> string list
40+
val basenames : t -> string list
4141
(** All the files in that directory. This doesn't include files in
4242
sub-directories of this directory. *)
4343
end

ocaml/utils/misc.ml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,10 +360,17 @@ module Stdlib = struct
360360
in
361361
helper chars str []
362362

363-
let split_last_exn str ~split_on =
363+
let split_once str ~idx =
364364
let n = String.length str in
365+
String.sub str 0 idx, String.sub str (idx + 1) (n - idx - 1)
366+
367+
let split_last_exn str ~split_on =
365368
let ridx = String.rindex str split_on in
366-
String.sub str 0 ridx, String.sub str (ridx + 1) (n - ridx - 1)
369+
split_once str ~idx:ridx
370+
371+
let split_first_exn str ~split_on =
372+
let idx = String.index str split_on in
373+
split_once str ~idx
367374

368375
let starts_with ~prefix s =
369376
let len_s = length s

0 commit comments

Comments
 (0)