ocamlfind(1)

πŸ“¦
version 1.9.8 Β· 3 versions
, in arch rolling, debian trixie, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, ubuntu questing, ubuntu resolute, ubuntu stonking

ocamlfind β€” the command-line interface of the package manager πŸ’–

okay bestie, buckle up, we're doing the findlib thing. this is ocamlfind(1), from the General Commands Manual, and it is a lot β€” but every bit of it matters, so we're going through it together, no skimming, no "eh I'll figure it out later". periodt. πŸ’…


NAME ✨

ocamlfind β€” the command-line interface of the Package manager πŸŽ€


SYNOPSIS πŸ¦‹

       ocamlfind query [-help | other options] package_name ...
   or: ocamlfind ocamlc [-help | other options] file ...
   or: ocamlfind ocamlcp [-help | other options] file ...
   or: ocamlfind ocamlmktop [-help | other options] file ...
   or: ocamlfind ocamlopt [-help | other options] file ...
   or: ocamlfind ocamldoc [-help | other options] file ...
   or: ocamlfind ocamldep [-help | other options] file ...
   or: ocamlfind ocamlmklib [-help | other options] file ...
   or: ocamlfind ocamlbrowser [-help | other options]
   or: ocamlfind install [-help | other options] package_name file ...
   or: ocamlfind remove [-help | other options] package_name
   or: ocamlfind lint META
   or: ocamlfind list [-describe]
   or: ocamlfind printppx [-help | other options] package_name ...
   or: ocamlfind printconf [ variable ]
   or: ocamlfind package/command arg ...

       Optional toolchain selection by:
         ocamlfind -toolchain name ...

so many entry points and honestly? she serves in every single one of them. πŸ’–


THE 'query' SUBCOMMAND πŸ”

Synopsis

       ocamlfind query [ -predicates p  |
                         -format f |
                         -long-format | -l |
                         -i-format |
                         -l-format |
                         -a-format |
                         -o-format |
                         -p-format |
                         -prefix p |
                         -separator s |
                         -suffix s |
                         -pp |
                         -descendants | -d |
                         -recursive  | -r
                         -qe | -qo] package ...

Description

this command looks packages up, optionally sorts them, and prints their attributes. like, it's the girl who knows where everyone lives and what they're about. 🫢

if you don't pass -recursive (short: -r), it looks up exactly the packages you named on the command line. if -recursive is there, you get those packages plus all their ancestors β€” or, if -descendants (short: -d) is also there, all their descendants too.

package lookup and which attributes get selected can both be tweaked by specifying predicates. if you don't give a -predicates option, the empty set of predicates is used. and listen β€” even the lookup itself is influenced by the actual set of predicates, because the "requires" variables can be conditional. iykyk. πŸ’…

what actually gets printed about a package depends on the format you picked, and there are a bunch of options that modify that format. some formats denote sets of values (like -format %a), and in that case multiple output records get printed for every package. (you can technically specify formats denoting the Cartesian product of sets, like -format %a%o, but bestie... it does not make sense. don't.) before the first output record the prefix is printed, and the suffix after the last record. between two records, the separator is printed. 🌸

Options

  • -predicates p β€” sets the set of actual predicates. the argument p is a list of predicate names separated by commas and/or whitespace. if you pass multiple -predicates options, the union of all the specified sets is effectively what gets used. πŸ’œ
  • -format f β€” sets the format to the string f. characters preceded by a percent sign are interpreted as placeholders; all other characters mean themselves. the defined placeholders are listed below. the default format is "%d".
  • -long-format or -l β€” sets the format such that all relevant variables are printed.
  • -i-format β€” same as -format "-I %d", i.e. directory options for ocamlc are printed.
  • -l-format β€” same as -format "-ccopt -L%d", i.e. directory options for the linker backend are printed.
  • -a-format β€” same as -format "%+a", i.e. archive file names are printed.
  • -o-format β€” same as -format "%o", i.e. linker options are printed.
  • -p-format β€” same as -format "%p", i.e. package names are printed.
  • -prefix p β€” sets the prefix that is printed before the first output record to the given string. the default prefix is the empty string.
  • -suffix s β€” sets the suffix that is printed after the last output record to the given string. the default suffix is the empty string.
  • -separator s β€” sets the separator that is printed between output records to the given string. the default separator is a linefeed character.
  • -recursive or -r β€” not only the packages given on the command line are queried, but also all ancestors or descendants. if the option -descendants is specified too, the descendants are printed, otherwise the ancestors. the packages are topologically sorted. πŸ‘‘
  • -descendants -d β€” instead of the ancestors, the descendants of the given packages are queried. this option implies -recursive.
  • -pp β€” query preprocessor packages (camlp4 syntax extensions). normally you don't need to set -predicates, except you need the archives (then add -predicates byte). this option implies -recursive.
  • -qe β€” do not print most errors to stderr, just set the exit code.
  • -qo β€” do not print the regular output.

Placeholders meaningful in the -format option πŸŽ€

  • %% β€” replaced by a single percent sign.
  • %p β€” replaced by the package name.
  • %d β€” replaced by the package directory.
  • %m β€” replaced by the path to the META file (new since findlib-1.6).
  • %D β€” replaced by the package description.
  • %v β€” replaced by the version string.
  • %a β€” replaced by the archive filename. if there is more than one archive, a separate output record is printed for every archive.
  • %+a β€” like %a, but the filenames are converted to absolute paths ("+" and "@" notations are resolved).
  • %A β€” replaced by the list of archive filenames.
  • %+A β€” like %A, but the filenames are converted to absolute paths ("+" and "@" notations are resolved).
  • %o β€” replaced by one linker option. if there is more than one option, a separate output record is printed for every option.
  • %O β€” replaced by the list of linker options.
  • %(property) β€” replaced by the value of the property named in parentheses, or the empty string if not defined.

THE SUBCOMMANDS 'ocamlc', 'ocamlcp', 'ocamlopt', and 'ocamlmktop' 🧚

Synopsis

       ocamlfind ( ocamlc | ocamlcp | ocamlopt | ocamlmktop )
                 [ -package package-name-list |
                   -linkpkg |
                   -predicates pred-name-list |
                   -dontlink package-name-list |
                   -syntax pred-name-list |
                   -ppopt camlp4-arg |
                   -ppxopt package,arg |
                   -dllpath-pkg package-name-list |
                   -dllpath-all |
                   -passopt arg |
                   -passrest arg... |
                   -only-show |
                   standard-option ]
                 file ...

Description

these subcommands are drivers for the compilers with the same names β€” i.e. "ocamlfind ocamlc" is a driver for "ocamlc", and so on. so like, ocamlfind is the girl holding the aux cable, and the compiler is the speaker. 🎢

the subcommands understand all documented options of the compilers (here called standard-options), plus a few extra ones. if you invoke these subcommands with only standard options, they behave as if the underlying compiler had been called directly. the extra options are what modify that behaviour.

internally, these subcommands transform the given list of options and file arguments into an invocation of the driven compiler. this transformation only adds options and files, and the relative order of the options and files passed directly is unchanged. no cap.

if there are -package options, additional directory search specifiers get included ("-I", and "-ccopt -I"), such that files of all named packages and all ancestors can be found. πŸ¦‹

the -linkpkg option causes the packages listed in the -package options and all necessary ancestors to be linked in. what that means: the archive files implementing the packages are inserted into the list of file arguments.

since the package database is queried, a set of predicates is needed. most predicates are set automatically (see below), but additional predicates can be given by a -predicates option.

if there is a -syntax option, the drivers assume that a preprocessor is to be used. in that case, the preprocessor command is built first in a preprocessor stage, and this command is passed to the compiler using the -pp option. the set of predicates in the preprocessor stage is different from the set in the compiler/linker stage. two different vibes, one pipeline. ✨

Options for compiling and linking

here, only the additional options not interpreted by the compiler but by the driver itself, and options with additional effects, are explained. some options are only meaningful for the preprocessor call, and are explained below. πŸ‘‡

  • -package package-name-list β€” adds the listed package names to the set of included packages. the package names may be separated by commas and/or whitespace. in the transformed command, for every package of the set of included packages and for any ancestor, a directory search option is inserted after the already given options. this means that "-I" and "-ccopt -I" options are added for every package directory. πŸ’…
  • -linkpkg β€” causes that in the transformed command all archives of the packages specified by -packages and all their ancestors are added to the file arguments. more precisely, these archives are inserted before the first given file argument. furthermore, "-ccopt -L" options for all package directories, and the linker options of the selected packages, are added too. note that the archives are inserted in topological order while the linker options are added in reverse topological order. yes, that's on purpose, don't @ me. 😭
  • -predicates pred-name-list β€” adds the given predicates to the set of actual predicates. the predicates must be separated by commas and/or whitespace.
  • -dontlink package-name-list β€” this option modifies the behaviour of -linkpkg. packages specified here and all ancestors are not linked in. again the packages are separated by commas and/or whitespace.
  • -dllpath-pkg package-name-list β€” for these packages, -dllpath options are added to the compiler command. this may be useful when the ld.conf file is not properly configured.
  • -dllpath-all β€” for all linked packages, -dllpath options are added to the compiler command. this may be useful when the ld.conf file is not properly configured.
  • -passopt arg
  • -passopt arg β€” bestie, this arg goes straight to the underlying compiler, no detours, no vibe check. You'd use this when you need to sneak in compiler options that are undocumented. iykyk πŸ’…
  • -passrest arg... β€” same energy as above but for everything that comes after: all following arg... get yeeted directly at the underlying compiler. Again, this is the move for undocumented compiler options. periodt ✨
  • -only-show β€” okay so this one just prints the constructed command (ocamlc/ocamlopt) to stdout and then... does not run it. that's it. it's for the unlikely event that you need a wrapper around ocamlfind. niche but iconic πŸŽ€
  • -verbose β€” this standard option is interpreted by the driver too. yes queen, the driver reads it as well πŸ’–
  • -thread β€” this standard option makes the predicate "mt" get added to the set of actual predicates. if POSIX threads are available, the predicate "mt_posix" is selected too. if only VM threads are available, the predicate "mt_vm" gets included into the set, and the compiler switch is changed into -vmthread. 🧡
⚠️ heads up: the presence of the "mt" predicate triggers special fixup of the dependency graph (see below). not a drill bestie
  • -vmthread β€” this standard option makes the predicates "mt" and "mt_vm" get added to the set of actual predicates. πŸ¦‹
⚠️ again: the presence of the "mt" predicate triggers special fixup of the dependency graph (see below). same rule, no exceptions
  • -p β€” this standard option of "ocamlopt" makes the predicate "gprof" get added to the set of actual predicates. πŸ“ˆ

✨ Options for preprocessing ✨

the options that actually matter for the preprocessor are these ones, and they're lowkey the whole personality of this stage:

  • -package package-name-list β€” these packages get considered while looking up the preprocessor arguments. and no, it's not a problem that the same -package option is used for this purpose, because the set of predicates is different. if you're gonna use the preprocessor, it's recommended to mention at least camlp4 here. fr fr 🫢
  • -syntax pred-name-list β€” these predicates are assumed to be true in addition to the standard preprocessor predicates. see below for the list, bestie πŸ“‹
  • -ppopt camlp4-arg β€” this argument gets passed to the camlp4 call. simple as 🌸
  • -ppxopt package,arg β€” adds arg to the ppx preprocessor invocation specified via the "ppx" property in the META file of package. πŸ’œ

πŸŽ€ Predicates for compiling and linking πŸŽ€

  • byte β€” the "byte" predicate means one of the bytecode compilers is being used. it gets automatically included into the predicate set if the "ocamlc", "ocamlcp", or "ocamlmktop" compiler is used. ⭐
  • native β€” the "native" predicate means the native compiler is being used. automatically included into the predicate set if the "ocamlopt" compiler is used. πŸ”₯
  • toploop β€” the "toploop" predicate means the toploop is available in the linked program. this predicate is only set when the toploop is actually being executed, not when the toploop is created. (this changed in version 1.0.4 of findlib, bestie, write that down πŸ“)
  • create_toploop β€” this predicate means a toploop is being created (using ocamlmktop). πŸ‘‘
  • mt β€” the "mt" predicate means the program is multi-threaded. it gets automatically included into the predicate set if the -thread option is given. 🧡
  • mt_posix β€” the "mt_posix" predicate means that, in the case "mt" is set too, the POSIX libraries are used to implement threads. "mt_posix" is automatically included into the predicate set if the variable "type_of_threads" in the META description of the "threads" package has the value "posix". this is normally the case if "findlib" is configured for POSIX threads. πŸ’…
  • mt_vm β€” the "mt_vm" predicate means that, in the case "mt" is set too, the VM thread emulation is used to implement multi-threading. πŸ¦‹
  • gprof β€” the "gprof" predicate means that, in the case "native" is set too, the program is compiled for profiling. it gets automatically included into the predicate set if "ocamlopt" is used and the -p option is in effect. πŸ“Š
  • autolink β€” the "autolink" predicate means ocamlc is able to perform automatic linking. it's automatically included into the predicate set if ocamlc knows automatic linking (from version 3.00), but it is not set if the -noautolink option is set. πŸ”—
  • syntax β€” this predicate is set if there's a -syntax option. it's set both for the preprocessor</> and the compiler/linker stage, and it can be used to find out whether the preprocessor is enabled or not. 🎯

🌈 Predicates for preprocessing 🌈

  • preprocessor β€” this predicate is always set while looking up the preprocessor arguments. it can be used to tell the difference between the preprocessor stage and the compiler/linker stage. 🫧
  • syntax β€” this predicate is set if there's a -syntax option. it's set both for the preprocessor and the compiler/linker stage, and it can be used to find out whether the preprocessor is enabled or not. (yes, it shows up in both lists, it's just like that 😌)
  • camlp4o β€” this is the reserved predicate for the standard OCaml syntax. it can be used in the -syntax predicate list. πŸ“—
  • camlp4r β€” this is the reserved predicate for the revised OCaml syntax. it can be used in the -syntax predicate list. πŸ“˜

πŸ’« Special behaviour of 'ocamlmktop' πŸ’«

so there's this special module Topfind that supports loading packages in scripts, right? because of that, the "ocamlmktop" subcommand can add initialization code for this module. this extra code is linked into the executable if "findlib" is in the set of effectively linked packages. cute, right? πŸŽ€


πŸ”§ Fixup of the dependency graph for multi-threading πŸ”§

for a number of reasons, the presence of the "mt" predicate triggers that:

  1. the package "threads" is added to the list of required packages, and
  2. the package "threads" becomes a prerequisite of all other packages (except of itself and a few hardcoded exceptions).

the effect is that the options -thread and -vmthread automatically select the "threads" package, and that "threads" gets inserted at the right position in the package list. no cap, it's doing all that for you πŸ’…


πŸ¦‹ Extended file naming πŸ¦‹

at a number of places you can refer to files not only by absolute or relative path names, but also by extended names. these have two major forms:

  • +name refers to the subdirectory name of the standard library directory
  • @name refers to the package directory of the package name

both forms can be continued by a path, like for example @netstring/netstring_top.cma. iconic ✨

you can use extended names:

  1. with -I options,
  2. as normal file arguments of the compiler,
  3. in the "archive" property of packages.

πŸ‘‘ How to set the names of the compiler executables πŸ‘‘

normally, the OCaml bytecode compiler can be called under the name ocamlc. but bestie, that's not always true β€” sometimes a different name is chosen. πŸ™ˆ

you can instruct ocamlfind to call executables with other names than ocamlc, ocamlopt, ocamlmktop, and ocamlcp. if present, the environment variable OCAMLFIND_COMMANDS is interpreted as a mapping from the standard names to the actual names of the executables. it has to have this format, exactly:

standardname1=actualname1 standardname2=actualname2 ...

example: you may set OCAMLFIND_COMMANDS like this:

OCAMLFIND_COMMANDS='ocamlc=ocamlc-3.00 ocamlopt=ocamlopt-3.00'
export OCAMLFIND_COMMANDS

alternatively, you can change the configuration file findlib.conf. your call, main character 🌟


πŸ’– THE SUBCOMMAND 'ocamlmklib' πŸ’–

Synopsis

ocamlfind ocamlmklib
          [ -package package-name-list |
            -predicates pred-name-list |
            -dllpath-pkg package-name-list |
            -dllpath-all |
            -passopt arg |
            -passrest arg... |
            standard-option ]
            file ...

Description

this is a wrapper around ocamlmklib, and it creates library archives and DLLs. on top of the standard options, you can use -package to add the search path of packages. 🎁

⚠️ note that no predicates are set by default β€” the wrapper does not know whether this is about byte or native code linking. it's not being mysterious, it genuinely doesn't know πŸ’€

this wrapper is mostly provided for completeness. that's the whole tea β˜•


🌸 THE 'ocamldep' SUBCOMMAND 🌸

Synopsis

ocamlfind ocamldep [-package package-name-list |
                    -syntax pred-name-list |
                    -ppopt camlp4-arg |
                    -passopt arg |
                    -passrest arg... |
                    -verbose |
                    standard-option] file ...

Description

this command is a driver for the tool</> ocamldep of the OCaml distribution. and ngl, this driver is only useful in conjunction with the preprocessor camlp4; otherwise it does not provide more functions than ocamldep itself. so like, if you're not using camlp4, just... use ocamldep? πŸ™ˆ

Options

here, only the additional options not interpreted by ocamldep but by the driver itself, and options with additional effects, are explained. the rest is somebody else's business πŸ’…

  • -package package-name-list β€” the packages named here are only used to look up the preprocessor options. the package camlp4 should be specified anyway, but further packages that add capabilities to the preprocessor can also be passed. πŸŽ€
  • -syntax pred-name-list β€” the predicates that are in effect during the look-up of the preprocessor options. at least, either camlp4o (selecting the normal syntax) or camlp4r (selecting the revised syntax) should be specified. pick one bestie, don't be shy 🌟
  • -ppopt camlp4-arg β€” an option that gets passed through to the camlp4 call. πŸ¦‹
  • -passopt arg β€” an option that gets passed through to the ocamldep call. πŸ’œ
  • -passrest arg... β€” all further arguments are passed down to ocamldep unprocessed. zero touch, zero thoughts, just vibes ✨
  • -verbose β€” displays the resulting ocamldep command (for debugging). πŸ”

Example

a typical way of using this driver:

ocamlfind ocamldep -package camlp4,xstrp4 -syntax camlp4r file1.ml file2.ml

this command outputs the dependencies of file1.ml and file2.ml, although these modules make use of the syntax extensions provided by xstrp4 and are written in revised syntax. see? it ate and left no crumbs πŸ‘‘

🌈 THE 'ocamlbrowser' SUBCOMMAND 🌈

πŸ’« Synopsis πŸ’«

ocamlfind ocamlbrowser [-package package-name-list |
                        -all |
                        -passopt arg
                        -passrest ]

🫢 Description 🫢

okay so this driver literally just calls ocamlbrowser but with package options baked in. give it -package and the packages you named get dropped into the browser's search path, so their modules become visible on top of the standard library. and then -all? that's the "gimme everything" button β€” every single package managed by findlib gets selected. main character energy fr.

and same as the other drivers, -passopt and -passrest let you yeet arguments straight through to the ocamlbrowser program itself. iykyk πŸ’…


πŸŽ€ THE SUBCOMMAND 'ocamldoc' πŸŽ€

✨ Synopsis ✨

ocamlfind ocamldoc
          [ -package package-name-list |
            -predicates pred-name-list |
            -syntax pred-name-list |
            -ppopt camlp4-arg |
            standard-option ]
          file ...

🌸 Description 🌸

this one is a driver for ocamldoc, bestie. it understands every option ocamldoc supports plus the findlib ones listed up there. basically the -package options get translated into -I options, and the syntax options you pick get translated into camlp4 options. cute, right?

πŸ‘‘ Options πŸ‘‘

heads up: here we're only explaining the extra options that the driver itself handles (not the ones ocamldep deals with), plus any options that do something extra on top. no cap.

  • -package package-name-list β€” adds the listed package names to the set of included packages. the package names can be separated by commas and/or whitespace, whatever vibe you're feeling. in the transformed command, for every package in the set of included packages and for any ancestor, a directory search option gets inserted after the options you already gave. so like, -I options get added for every package directory. πŸ’–
  • -predicates pred-name-list β€” adds the given predicates to the set of actual predicates. the predicates must be separated by commas and/or whitespace.
  • -syntax pred-name-list β€” these are the predicates that are in effect while the preprocessor options are being looked up. at minimum you should specify either camlp4o (which selects the normal syntax) or camlp4r (which selects the revised syntax). pick your fighter ✨
  • -ppopt camlp4-arg β€” an option that gets passed straight through to the camlp4 call.

πŸ’… THE 'install' SUBCOMMAND πŸ’…

πŸ¦‹ Synopsis πŸ¦‹

ocamlfind install [ -destdir directory ]
                  [ -metadir directory ]
                  [ -ldconf path ]
                  [ -dont-add-directory-directive ]
                  [ -patch-version string ]
                  [ -patch-rmpkg name ]
                  [ -patch-archives ]
                  [ -dll ] [ -nodll ] [ -optional ] [ -add ]
                  package_name file ...

πŸ’œ Description πŸ’œ

okay so this subcommand installs a shiny new package, either at the default location (that's the destdir variable from findlib.conf, bestie) or wherever you point it with -destdir. what actually happens: a brand new package directory gets created, and the files on the command line get copied into it. required: a META file has to be one of the files you copy to the target directory. no META, no party. 😭

heads up: package directories should be flat β€” no subdirectories, periodt. and existing packages are never overwritten. never ever.

so you can have a separate directory for all your META files if that's your thing. to do that, either set the metadir variable of findlib.conf, or just pass -metadir. when you do, the file called META gets copied into that specified directory and renamed to META.p (where p is the package name), while all the other files go to the package directory like normal. also the META file gets modified so that its directory variable contains the path of the package directory. iconic. ✨

the -dont-add-directory-directive option stops the installer from adding that directory variable at all.

now: if there are files ending in .so or .dll, the package directory gets added to the DLL configuration file ld.conf, so the dynamic loader can actually find the DLL. you can override where that file lives with -ldconf. and to turn this whole feature off, say -ldconf ignore β€” that means the ld.conf file doesn't get touched.

but β€” plot twist β€” if there's a stublibs directory inside site-lib, the DLLs are not installed into the package directory. instead they go into that stublibs directory, which is shared by all packages installed at the same location. in that case ld.conf isn't modified at all, so you don't need to say -ldconf ignore if this is the install style you prefer. slay πŸŽ€

-dll and -nodll let you control exactly which files count as DLLs and which don't. by default the suffix rule is in effect: files ending in .so (Unix) or .dll (Windows) are DLLs. -dll flips that β€” all the following files are DLLs no matter what their suffix is. -nodll says the following files are not DLLs, even if they have a DLL-looking suffix. for example, in this call, f1 and f2 get handled by the suffix rule, f3 and f4 are DLLs anyway, and f5 and f6 are not DLLs:

ocamlfind install p f1 f2 -dll f3 f4 -nodll f5 f6

-optional declares that all following files are optional β€” meaning the command won't fail if those files don't exist. very forgiving of it 🫢

the -patch options can change the contents of the META files while they're being installed. -patch-version changes the contents of the top-level version variable. -patch-rmpkg removes the given subpackage. and -patch-archives is experimental β€” specifically it removes all non-existing files from archive variables, and even whole subpackages if the archives are missing. πŸ’€

and -add? its whole effect is to add more files to packages that are already installed. that's it, that's the vibe.


🌸 THE 'remove' SUBCOMMAND 🌸

🌟 Synopsis 🌟

ocamlfind remove [ -destdir directory ]
                 [ -metadir directory ]
                 [ -ldconf path ]
                 package_name

πŸ“ Description πŸ“

the package gets removed if it's installed at the default location (you guessed it β€” the destdir variable of findlib.conf). if the package lives somewhere else, it will not be removed by default. but you can pass an alternate directory with -destdir and then it will. (it must be the same directory you specified at installation time, okay? no funny business.)

note: package directories should be flat (no subdirectories), because this subcommand literally cannot remove deep package directories.

if you've got a separate directory for META files, you have to either configure it via the metadir variable of findlib.conf, or specify -metadir.

the command does not fail if the package and/or the META file can't be found β€” you just get a warning in that case. it's giving "no thoughts, head empty, no errors." 😌

if the package directory is mentioned in the ld.conf configuration file for DLLs, it'll try to remove that entry from the file. override the file's location with -ldconf. to turn this off, use -ldconf ignore β€” then ld.conf is not modified.

and if there's a stublibs directory, it checks whether the package owns any of the files in there, and the owned files get deleted. bye bestie πŸ’…


✨ THE 'list' SUBCOMMAND ✨

πŸ’– Synopsis πŸ’–

ocamlfind list [-describe]

πŸ¦‹ Description πŸ¦‹

this command lists all the packages in the search path. and if you tack on -describe, it outputs the package descriptions too. simple, clean, gorgeous. 🌈


🧚 THE 'printppx' SUBCOMMAND 🧚

⭐ Synopsis ⭐

ocamlfind printppx
          [ -predicates pred-name-list ]
          [ -ppxopt package,arg ]
          package ...

πŸ’« Description πŸ’«

this command prints out the ppx preprocessor options exactly as they would appear in an OCaml compiler invocation for the packages you listed. the output includes one -ppx option for each preprocessor. the possible options mean the same thing as they do for ocamlfind ocamlc. -predicates adds assumed predicates, and -ppxopt package,arg adds arg to the ppx invocation of package package.

okay so real talk, this is a trap: the output of ocamlfind printppx will contain quotes " for ppx commands that contain space-separated arguments. in that case $(ocamlfind printppx ...) won't work like you naively expected, because lots of shells (bash and dash included) do field splitting on the result of command substitutions without honoring quotes. so like. be aware. 😭

πŸ”₯ THE 'lint' SUBCOMMAND πŸ”₯

πŸŽ€ Synopsis πŸŽ€

ocamlfind lint file

πŸ’… Description πŸ’…

checks the META file and reports possible problems. that's the whole thing β€” your little META-file health check-up. 🩺


🌈 THE 'printconf' SUBCOMMAND 🌈

πŸ’œ Synopsis πŸ’œ

ocamlfind printconf [ conf | path | destdir | metadir | metapath | stdlib | ldconf ]

✨ Description ✨

this command prints the effective configuration β€” meaning after reading the configuration file and after applying all the various environment variables that override settings. so it's the truth, the whole truth, nothing but. πŸ‘‘

called with no arguments? it prints all the configuration options in a human-readable form. called with an argument? it prints only the value of the requested option, with no explaining text. just the goods.

  • conf β€” prints the location of the configuration file findlib.conf.
  • path β€” prints the search path for packages. the members of the path are separated by linefeeds.
  • destdir β€” prints the location where packages are installed and removed by default.
  • metadir β€” prints the location where META files are installed and removed (that's if the alternative layout is being used).
  • metapath β€” prints the path where the META file is installed for a fictive package. the package name is marked with %s in the path. for instance, this command could output /some/path/%s/META or /some/path/META.%s, depending on the layout.
  • stdlib β€” prints the location of the standard library.
  • ldconf β€” prints the location of the ld.conf file.

🫢 THE SUBCOMMAND CALLING PACKAGE PROGRAMS 🫢

🌟 Synopsis 🌟

ocamlfind pkg/cmd argument ...

πŸ“ Description πŸ“

okay this one is so useful β€” it calls programs that are installed inside package directories. it looks up the directory for pkg and then calls the command named cmd inside that directory. any remaining arguments get passed along to that command. bestie behavior fr.

so like, argv(0) contains the absolute path to the command, and argv(1) plus the following argv entries contain the arguments. and the working directory is not changed. we stay put. πŸ’–

example time: to call the program x that's installed in package p, with arguments y and z, you run:

ocamlfind p/x y z

iconic. periodt. πŸŽ€


πŸ’« CONFIGURATION FILE, ENVIRONMENT VARIABLES πŸ’«

the configuration file and the environment variables are all documented over in the manual page for findlib.conf. go read that one next, bestie, it's got the lore. πŸ“–βœ¨

πŸ› οΈ HOW TO SET THE TOOLCHAIN πŸ’…

πŸ“œ Synopsis

ocamlfind -toolchain name ...

πŸ’– Description

Okay bestie, listen β€” the -toolchain option is that girl, and she gets to go first. Before any other command, she's up. Like, no cap, she needs to be at the front of the line. Here's the vibe:

ocamlfind -toolchain foo ocamlc -c file.ml

That compiles file.ml with toolchain "foo". ✨ Yes queen.

The whole point? By selecting toolchains you can switch to different command sets. Obsessed. For instance, the toolchain "foo" may consist of a patched ocamlc compiler. So like, a whole different compiler personality, iykyk. πŸ”₯

🫢 Wanna actually configure these toolchains? Go read findlib.conf β€” that's where the magic happens, bestie. See how to configure toolchains there.

and that's a wrap on ocamlfind(1), bestie πŸŽ€

This iconic lil page is from the User Manual of The findlib package manager for OCaml, and it's filed under ocamlfind(1) β€” literally the main character of the section, no competition. πŸ’…βœ¨ Go forth and slay your builds, fr fr. πŸ’–πŸ¦‹πŸŒΈ