Skip to content

Careful library deps #1192

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

Closed
wants to merge 4 commits into from
Closed
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: 1 addition & 1 deletion src/driver/compile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ let link : compiled list -> _ =
fun c ->
let link input_file output_file =
let { Odoc_unit.libs; pages } = c.pkg_args in
let includes = c.include_dirs |> Fpath.Set.of_list in
let includes = Fpath.Set.of_list c.include_dirs in
Odoc.link ~input_file ~output_file ~includes ~libs ~docs:pages
~current_package:c.pkgname ()
in
Expand Down
5 changes: 4 additions & 1 deletion src/driver/dune_style.ml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@ let of_dune_build dir =
let cmtidir =
Fpath.(path / Printf.sprintf ".%s.objs" libname / "byte")
in
let all_lib_deps = Util.StringMap.empty in
(* TODO *)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you intend to implement that for voodoo and dune in this PR too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was putting it off, it's a bit of a PITA, especially for the dune mode!

let pkg_dir = Fpath.rem_prefix dir path |> Option.get in
( pkg_dir,
Packages.Lib.v
~libname_of_archive:(Util.StringMap.singleton libname libname)
~pkg_name:libname ~dir:path ~cmtidir:(Some cmtidir) ))
~pkg_name:libname ~dir:path ~cmtidir:(Some cmtidir)
~all_lib_deps ))
libs
in
let packages =
Expand Down
11 changes: 9 additions & 2 deletions src/driver/library_names.ml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@
[archive_name], and that for this cma archive exists a corresponsing
[archive_name].ocamlobjinfo file. *)

type library = { name : string; archive_name : string; dir : string option }
type library = {
name : string;
archive_name : string;
dir : string option;
deps : string list;
}

let read_libraries_from_pkg_defs ~library_name pkg_defs =
try
let cma_filename = Fl_metascanner.lookup "archive" [ "byte" ] pkg_defs in
let deps_str = Fl_metascanner.lookup "requires" [] pkg_defs in
let deps = Astring.String.fields deps_str in
let dir =
List.find_opt (fun d -> d.Fl_metascanner.def_var = "directory") pkg_defs
in
Expand All @@ -25,7 +32,7 @@ let read_libraries_from_pkg_defs ~library_name pkg_defs =
else cma_filename
in
if String.length archive_name > 0 then
[ { name = library_name; archive_name; dir } ]
[ { name = library_name; archive_name; dir; deps } ]
else []
with Not_found -> []

Expand Down
7 changes: 6 additions & 1 deletion src/driver/library_names.mli
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
type library = { name : string; archive_name : string; dir : string option }
type library = {
name : string;
archive_name : string;
dir : string option;
deps : string list;
}

val process_meta_file : Fpath.t -> library list
(** From a path to a [Meta] file, returns the list of libraries defined in this
Expand Down
81 changes: 41 additions & 40 deletions src/driver/odoc_unit.ml
Original file line number Diff line number Diff line change
Expand Up @@ -43,58 +43,53 @@ let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
in
let index_dir = match index_dir with None -> output_dir | Some dir -> dir in
(* This isn't a hashtable, but a table of hashes! Yay! *)
let hashtable =
let hashtable, lib_dirs =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are using StringMap quite a lot, why not use that instead of an associative list?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, let's do that

let open Packages in
let h = Util.StringMap.empty in
List.fold_left
(fun h pkg ->
(fun (h, lds) pkg ->
List.fold_left
(fun h lib ->
List.fold_left
(fun h mod_ ->
Util.StringMap.add mod_.m_intf.mif_hash
(pkg, lib.lib_name, mod_) h)
h lib.modules)
h pkg.libraries)
h pkgs
(fun (h, lds) lib ->
let h' =
List.fold_left
(fun h mod_ ->
Util.StringMap.add mod_.m_intf.mif_hash (pkg, lib, mod_) h)
h lib.modules
in
let lib_dir =
Fpath.(output_dir // pkg.Packages.pkg_dir / "lib" / lib.lib_name)
in
(h', (lib.lib_name, lib_dir) :: lds))
(h, lds) pkg.libraries)
(h, []) pkgs
in
(* This one is a hashtable *)
let cache = Hashtbl.create 10 in
let pkg_args_of pkg : pkg_args =
let pkg_args_of pkg lib_deps : pkg_args =
let pages =
[
(pkg.Packages.name, Fpath.(output_dir // pkg.Packages.pkg_dir / "doc"));
]
in
let libs =
List.map
(fun lib ->
( lib.Packages.lib_name,
Fpath.(output_dir // pkg.Packages.pkg_dir / "lib" / lib.lib_name) ))
pkg.libraries
List.filter_map
(fun lib_name -> List.find_opt (fun (l, _) -> l = lib_name) lib_dirs)
lib_deps
in
{ pages; libs }
in
let pkg_args : pkg_args =
let pages, libs =
List.fold_left
(fun (all_pages, all_libs) pkg ->
let { pages; libs } = pkg_args_of pkg in
(pages :: all_pages, libs :: all_libs))
([], []) pkgs
in
let pages = List.concat pages in
let libs = List.concat libs in
{ pages; libs }
in
let index_of pkg =
let pkg_args = pkg_args_of pkg in
let pkg_args =
pkg_args_of pkg (List.map (fun l -> l.Packages.lib_name) pkg.libraries)
in
let output_file = Fpath.(index_dir / pkg.name / Odoc.index_filename) in
{ pkg_args; output_file; json = false; search_dir = pkg.pkg_dir }
in
let make_unit ~name ~kind ~rel_dir ~input_file ~pkg ~include_dirs : _ unit =
let make_unit ~name ~kind ~rel_dir ~input_file ~pkg ~include_dirs ~lib_deps :
_ unit =
let ( // ) = Fpath.( // ) in
let ( / ) = Fpath.( / ) in
let pkg_args = pkg_args_of pkg lib_deps in
let odoc_dir = output_dir // rel_dir in
let parent_id = rel_dir |> Odoc.Id.of_fpath in
let odoc_file = odoc_dir / (name ^ ".odoc") in
Expand All @@ -119,11 +114,13 @@ let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
match Util.StringMap.find_opt hash hashtable with
| None -> None
| Some (pkg, lib, mod_) ->
let result = of_intf mod_.m_hidden pkg lib mod_.m_intf in
let result =
of_intf mod_.m_hidden pkg lib.lib_name lib.lib_deps mod_.m_intf
in
Hashtbl.add cache mod_.m_intf.mif_hash result;
Some result)
deps
and of_intf hidden pkg libname (intf : Packages.intf) : intf unit =
and of_intf hidden pkg libname lib_deps (intf : Packages.intf) : intf unit =
match Hashtbl.find_opt cache intf.mif_hash with
| Some unit -> unit
| None ->
Expand All @@ -137,9 +134,9 @@ let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
in
let name = intf.mif_path |> Fpath.rem_ext |> Fpath.basename in
make_unit ~name ~kind ~rel_dir ~input_file:intf.mif_path ~pkg
~include_dirs
~include_dirs ~lib_deps
in
let of_impl pkg libname (impl : Packages.impl) : impl unit option =
let of_impl pkg libname lib_deps (impl : Packages.impl) : impl unit option =
let open Fpath in
match impl.mip_src_info with
| None -> None
Expand All @@ -161,21 +158,23 @@ let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
in
let unit =
make_unit ~name ~kind ~rel_dir ~input_file:impl.mip_path ~pkg
~include_dirs
~include_dirs ~lib_deps
in
Some unit
in

let of_module pkg libname (m : Packages.modulety) : [ impl | intf ] unit list
=
let i :> [ impl | intf ] unit = of_intf m.m_hidden pkg libname m.m_intf in
let of_module pkg libname lib_deps (m : Packages.modulety) :
[ impl | intf ] unit list =
let i :> [ impl | intf ] unit =
of_intf m.m_hidden pkg libname lib_deps m.m_intf
in
let m :> [ impl | intf ] unit list =
Option.bind m.m_impl (of_impl pkg libname) |> Option.to_list
Option.bind m.m_impl (of_impl pkg libname lib_deps) |> Option.to_list
in
i :: m
in
let of_lib pkg (lib : Packages.libty) : [ impl | intf ] unit list =
List.concat_map (of_module pkg lib.lib_name) lib.modules
List.concat_map (of_module pkg lib.lib_name lib.lib_deps) lib.modules
in
let of_mld pkg (mld : Packages.mld) : mld unit list =
let open Fpath in
Expand All @@ -195,6 +194,7 @@ let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
let name = mld_path |> Fpath.rem_ext |> Fpath.basename |> ( ^ ) "page-" in
let unit =
make_unit ~name ~kind ~rel_dir ~input_file:mld_path ~pkg ~include_dirs
~lib_deps:[]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anything bigger but still sensible we could use here?

  • We likely cannot add the union of the the lib_deps from the libraries of the package: I think there might be different deps with the same name? (not sure here).

I know we will provide a way to extend this, but having a bigger default would be nice!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the libraries in the package is what we decided before.

in
[ unit ]
in
Expand All @@ -210,6 +210,7 @@ let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
let unit =
let name = asset_path |> Fpath.basename |> ( ^ ) "asset-" in
make_unit ~name ~kind ~rel_dir ~input_file:asset_path ~pkg ~include_dirs
~lib_deps:[]
in
[ unit ]
in
Expand Down
21 changes: 19 additions & 2 deletions src/driver/packages.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ let pp_asset fmt m = Format.fprintf fmt "%a" Fpath.pp m.asset_path
type libty = {
lib_name : string;
archive_name : string;
lib_deps : string list;
modules : modulety list;
}

Expand Down Expand Up @@ -138,7 +139,7 @@ module Module = struct
end

module Lib = struct
let v ~libname_of_archive ~pkg_name ~dir ~cmtidir =
let v ~libname_of_archive ~pkg_name ~dir ~cmtidir ~all_lib_deps =
Logs.debug (fun m ->
m "Classifying dir %a for package %s" Fpath.pp dir pkg_name);
let dirs =
Expand Down Expand Up @@ -166,7 +167,8 @@ module Lib = struct
archive_name
in
let modules = Module.vs dir cmtidir modules in
Some { lib_name; archive_name; modules }
let lib_deps = Util.StringMap.find lib_name all_lib_deps in
Some { lib_name; archive_name; modules; lib_deps }
with _ ->
Logs.err (fun m ->
m "Error processing library %s. Ignoring." archive_name);
Expand Down Expand Up @@ -203,6 +205,20 @@ let of_libs ~packages_dir libs =
in
let all_libs = Util.StringSet.elements all_libs_set in
let all_libs = "stdlib" :: all_libs in
let all_lib_deps =
List.fold_right
(fun lib_name acc ->
match Ocamlfind.deps [ lib_name ] with
| Ok deps -> Util.StringMap.add lib_name deps acc
| Error (`Msg msg) ->
Logs.err (fun m ->
m
"Error finding dependencies of library '%s' through \
ocamlfind: %s"
lib_name msg);
acc)
all_libs Util.StringMap.empty
in
Logs.debug (fun m ->
m "Libraries to document: [%a]" Fmt.(list ~sep:sp string) all_libs);
let dirs' =
Expand Down Expand Up @@ -321,6 +337,7 @@ let of_libs ~packages_dir libs =

let libraries =
Lib.v ~libname_of_archive ~pkg_name:pkg.name ~dir ~cmtidir:None
~all_lib_deps
in
let libraries =
List.filter
Expand Down
2 changes: 2 additions & 0 deletions src/driver/packages.mli
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ val pp_asset : Format.formatter -> asset -> unit
type libty = {
lib_name : string;
archive_name : string;
lib_deps : string list;
modules : modulety list;
}

Expand All @@ -61,6 +62,7 @@ module Lib : sig
pkg_name:string ->
dir:Fpath.t ->
cmtidir:Fpath.t option ->
all_lib_deps:string list Util.StringMap.t ->
libty list
end

Expand Down
8 changes: 6 additions & 2 deletions src/driver/voodoo.ml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ let process_package pkg =
pkg.files
in

let all_lib_deps = Util.StringMap.empty in

(* TODO *)
let pkg_path =
Fpath.(v "prep" / "universes" / pkg.universe / pkg.name / pkg.version)
in
Expand Down Expand Up @@ -137,10 +140,11 @@ let process_package pkg =
(fun directory ->
Format.eprintf "Processing directory: %a\n%!" Fpath.pp directory;
Packages.Lib.v ~libname_of_archive ~pkg_name:pkg.name
~dir:directory ~cmtidir:None)
~dir:directory ~cmtidir:None ~all_lib_deps)
Fpath.(Set.to_list directories)))
metas
in

(* Check the main package lib directory even if there's no meta file *)
let extra_libraries =
let libdirs_without_meta =
Expand All @@ -163,7 +167,7 @@ let process_package pkg =
Packages.Lib.v ~libname_of_archive:Util.StringMap.empty
~pkg_name:pkg.name
~dir:Fpath.(pkg_path // libdir)
~cmtidir:None)
~cmtidir:None ~all_lib_deps)
libdirs_without_meta
in
Printf.eprintf "Found %d metas" (List.length metas);
Expand Down
1 change: 1 addition & 0 deletions src/odoc/bin/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,7 @@ end = struct
current_dir;
}
in
let directories = directories @ List.map ~f:snd lib_roots in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was about to say that this requires an update to the man for the -L option, but it was actually already saying that!

So whenever we can write {!/libname/Module} we can also write {!Module}.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure whether adding the paths to the include path was the best approach, or whether we should do something else elsewhere?

let resolver =
Resolver.create ~important_digests:false ~directories ~open_modules ~roots
in
Expand Down
8 changes: 2 additions & 6 deletions test/xref2/path_references.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@

$ odoc link -P pkg:h/pkg/doc -L libname:h/pkg/lib/libname h/pkg/doc/subdir/page-dup.odoc
$ odoc link -P pkg:h/pkg/doc -L libname:h/pkg/lib/libname h/pkg/doc/subdir/page-bar.odoc
File "doc/subdir/bar.mld", line 12, characters 49-56:
Warning: Failed to resolve reference unresolvedroot(Test) Couldn't find "Test"
File "doc/subdir/bar.mld", line 12, characters 39-48:
Warning: Failed to resolve reference ./Test Path 'Test' not found
File "doc/subdir/bar.mld", line 12, characters 18-38:
Expand All @@ -22,8 +20,6 @@
Warning: Failed to resolve reference unresolvedroot(foo) Couldn't find "foo"
$ odoc link -P pkg:h/pkg/doc -L libname:h/pkg/lib/libname h/pkg/doc/page-dup.odoc
$ odoc link -P pkg:h/pkg/doc -L libname:h/pkg/lib/libname h/pkg/doc/page-foo.odoc
File "doc/foo.mld", line 12, characters 37-44:
Warning: Failed to resolve reference unresolvedroot(Test) Couldn't find "Test"
File "doc/foo.mld", line 12, characters 27-36:
Warning: Failed to resolve reference ./Test Path 'Test' not found
File "doc/foo.mld", line 12, characters 0-9:
Expand Down Expand Up @@ -67,7 +63,7 @@ Helper that extracts references in a compact way. Headings help to interpret the
{"`Reference":[{"`Any_path":["`TCurrentPackage",["Test"]]},[]]}
{"`Reference":[{"`Resolved":{"`Identifier":{"`Root":[{"Some":{"`Page":[{"Some":{"`Page":[{"Some":{"`Page":["None","pkg"]}},"lib"]}},"libname"]}},"Test"]}}},[]]}
{"`Reference":[{"`Any_path":["`TRelativePath",["Test"]]},[]]}
{"`Reference":[{"`Root":["Test","`TUnknown"]},[]]}
{"`Reference":[{"`Resolved":{"`Identifier":{"`Root":[{"Some":{"`Page":[{"Some":{"`Page":[{"Some":{"`Page":["None","pkg"]}},"lib"]}},"libname"]}},"Test"]}}},[]]}
["Asset"]
{"`Reference":[{"`Resolved":{"`Identifier":{"`AssetFile":[{"`Page":[{"Some":{"`Page":["None","pkg"]}},"doc"]},"img.png"]}}},[]]}
{"`Reference":[{"`Resolved":{"`Identifier":{"`AssetFile":[{"`Page":[{"Some":{"`Page":["None","pkg"]}},"doc"]},"img.png"]}}},[]]}
Expand Down Expand Up @@ -95,7 +91,7 @@ Helper that extracts references in a compact way. Headings help to interpret the
{"`Reference":[{"`Any_path":["`TCurrentPackage",["libname","Test"]]},[]]}
{"`Reference":[{"`Any_path":["`TAbsolutePath",["pkg","libname","Test"]]},[]]}
{"`Reference":[{"`Any_path":["`TRelativePath",["Test"]]},[]]}
{"`Reference":[{"`Root":["Test","`TUnknown"]},[]]}
{"`Reference":[{"`Resolved":{"`Identifier":{"`Root":[{"Some":{"`Page":[{"Some":{"`Page":[{"Some":{"`Page":["None","pkg"]}},"lib"]}},"libname"]}},"Test"]}}},[]]}

$ odoc_print ./h/pkg/lib/libname/test.odocl | jq_references
["Page","foo"]
Expand Down
Loading