Index of opam packages, dune libraries and modules in an OCaml project
0

Configure Feed

Select the types of activity you want to include in your feed.

OCaml 98.6%
Dune 0.4%
Other 1.0%
106 1 0

Clone this repository

https://git.vm.fail/gazagnaire.org/ocaml-project-index https://git.vm.fail/did:plc:bwzbmqgcnqy76czspybab4lk
ssh://git@git.recoil.org:2222/gazagnaire.org/ocaml-project-index ssh://git@git.recoil.org:2222/did:plc:bwzbmqgcnqy76czspybab4lk

For self-hosted knots, clone URLs may differ based on your setup.


README.md

ocaml-project-index#

Index of packages, dune libraries, and modules in an OCaml project.

ocaml-project-index walks _opam/lib/, _build/install/default/lib/, and the source tree of a project, then answers questions that tools keep re-asking from raw filesystem state: which libraries a package provides, which libraries a package's source tree depends on, whether a library is only referenced from (test ...) stanzas, and which packages declare a pin-depends:. The walk runs once; the resulting in-memory record is queried by package, by typed package/library views, or by explicit inventory queries such as libraries_of_name.

The library is the shared scanning layer behind several tools in the blacksun monorepo: merlint dependency-declaration rules and monopam publish and push. Any future linter or package-management tool that needs opam-to-dune cross-references can build on it without re-parsing .opam files.

Install#

$ opam install ocaml-project-index

If opam cannot find the package, it may not yet be released in the public opam-repository. Add the overlay repository, then install it:

$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install ocaml-project-index

Usage#

Build an index once, query it many times:

open Project_index

(* Build the index once for the project rooted at [dir]. *)
let load fs dir = build ~fs ~monorepo:(Fpath.v dir) ()

(* Every package paired with the dune libraries it provides. *)
let package_libraries_by_name idx =
  packages idx
  |> List.filter_map (package idx)
  |> List.map (fun pkg ->
         (Package.name pkg, List.map Library.name (package_libraries pkg)))

(* Resolve a package's own [(libraries ...)] entries within its scope, so a
   same-named private helper in another package can't leak in. *)
let resolve_uses idx pkg_name names =
  match package idx pkg_name with
  | None -> []
  | Some pkg -> libraries_used_by pkg names

Find package documentation files that are not covered by an (mdx (files ...)) stanza:

let untested_package_docs idx pkg_name =
  match package idx pkg_name with
  | None -> []
  | Some pkg ->
      Package.doc_files pkg
      |> List.filter (fun (doc : doc_file) -> not doc.mdx)

What's in the index#

Each entry is keyed by a package name. Source-tree packages can come from .opam files, (package ...) stanzas in dune-project, or a package-less pure dune project (name ...).

Accessor What it answers
packages every package known to the index
origin Local (locally built) or Opam (installed dep)
libraries dune libraries provided by a package
source_dir filesystem location of the package's source metadata
tags tags: field of the .opam
depends runtime depends: (skips {with-test} / {with-doc})
test_depends {with-test} deps only
doc_depends {with-doc} deps only
pin_depends (lhs, url) pairs from pin-depends:
packages_with_pins packages whose .opam declares at least one pin-depends:
raw_opam exact contents of the source-tree .opam
raw_dune_project exact contents of the neighbouring dune-project
library_source_dir directory of the dune file declaring a library
library_libraries (libraries ...) field of a library's source stanza
Package.doc_files package-root .md / .mld files, tagged with MDX coverage
Library.doc_files library docs and .mli files, tagged with MDX coverage
test_only_libraries libraries referenced only from (test ...) / (tests ...) stanzas
runtime_library_uses libraries pulled in from (library ...) / public (executable ...)
test_library_uses libraries pulled in from (test ...) / private (executable ...)
package typed package view for package-scoped navigation
package_libraries typed libraries provided by a package
library_used_by resolve one already-observed (libraries ...) entry in a package's dependency cone
libraries_used_by resolve multiple already-observed (libraries ...) entries in that cone
libraries_of_name inventory lookup for all libraries with a name, preserving package identity
source_files non-vendored source files by default; pass ~include_vendored:true

Discovery sources#

The index combines three filesystem locations:

  • _opam/lib/<pkg>/ holds opam-installed external dependencies.
  • _build/install/default/lib/<pkg>/ holds locally built packages. It is scanned after _opam, so matching local builds replace installed package library metadata and origin comes out as Local.
  • The source tree is walked for <dir>/<pkg>.opam files and packages declared by dune-project ((package ...) or pure-project (name ...)) alongside their dune files. This populates source_dir, opam metadata when present, library_libraries, test_only_libraries, the raw file accessors, documentation files tagged by (mdx (files ...)), and the per-stanza-kind *_library_uses views.

When _opam/<pkg>/ has a dune-package, the index reads it for the authoritative library/module listing. Otherwise it falls back to a *.cmi scan, which gets the top-level library and its module names but not sub-library hierarchies (zarith.top etc.). The fallback is sufficient for the "is this name in scope?" question that callers typically have.

License#

ISC.