Dependency generator (ocamldep)

# Chapter 13 Dependency generator (ocamldep)

- Options
- A typical Makefile

The `ocamldep` command scans a set of OCaml source files (`.ml` and `.mli` files) for references to external compilation units, and outputs dependency lines in a format suitable for the `make` utility. This ensures that `make` will compile the source files in the correct order, and recompile those files that need to when a source file is modified.

The typical usage is:

            ocamldep options *.mli *.ml > .depend

where `*.mli *.ml` expands to all source files in the current directory and `.depend` is the file that should contain the dependencies. (See below for a typical `Makefile`.)

Dependencies are generated both for compiling with the bytecode compiler `ocamlc` and with the native-code compiler `ocamlopt`.

## 13.1 Options

The following command-line options are recognized by `ocamldep`.

`-I` directory
  Add the given directory to the list of directories searched for source files. If a source file `foo.ml` mentions an external compilation unit `Bar`, a dependency on that unit’s interface `bar.cmi` is generated only if the source for `bar` is found in the current directory or in one of the directories specified with `-I`. Otherwise, `Bar` is assumed to be a module from the standard library, and no dependencies are generated. For programs that span multiple directories, it is recommended to pass `ocamldep` the same `-I` options that are passed to the compiler.
`-ml-synonym` .ext
  Consider the given extension (with leading dot) to be a synonym for .ml.
`-mli-synonym` .ext
  Consider the given extension (with leading dot) to be a synonym for .mli.
`-modules`
  Output raw dependencies of the form

            filename: Module1 Module2 ... ModuleN

  where `Module1`, …, `ModuleN` are the names of the compilation units referenced within the file `filename`, but these names are not resolved to source file names. Such raw dependencies cannot be used by `make`, but can be post-processed by other tools such as `Omake`.
`-native`
  Generate dependencies for a pure native-code program (no bytecode version). When an implementation file (`.ml` file) has no explicit interface file (`.mli` file), `ocamldep` generates dependencies on the bytecode compiled file (`.cmo` file) to reflect interface changes. This can cause unnecessary bytecode recompilations for programs that are compiled to native-code only. The flag `-native` causes dependencies on native compiled files (`.cmx`) to be generated instead of on `.cmo` files. (This flag makes no difference if all source files have explicit `.mli` interface files.)
`-pp` command
  Cause `ocamldep` to call the given command as a preprocessor for each source file.
`-slash`
  Under Windows, use a forward slash (/) as the path separator instead of the usual backward slash (\). Under Unix, this option does nothing.
`-version`
  Print version string and exit.
`-vnum`
  Print short version number and exit.
`-help` or `--help`
  Display a short usage summary and exit.

## 13.2 A typical Makefile

Here is a template `Makefile` for a OCaml program.

    OCAMLC=ocamlc
    OCAMLOPT=ocamlopt
    OCAMLDEP=ocamldep
    INCLUDES=                 # all relevant -I options here
    OCAMLFLAGS=$(INCLUDES)    # add other options for ocamlc here
    OCAMLOPTFLAGS=$(INCLUDES) # add other options for ocamlopt here

    # prog1 should be compiled to bytecode, and is composed of three
    # units: mod1, mod2 and mod3.

    # The list of object files for prog1
    PROG1_OBJS=mod1.cmo mod2.cmo mod3.cmo

    prog1: $(PROG1_OBJS)
            $(OCAMLC) -o prog1 $(OCAMLFLAGS) $(PROG1_OBJS)

    # prog2 should be compiled to native-code, and is composed of two
    # units: mod4 and mod5.

    # The list of object files for prog2
    PROG2_OBJS=mod4.cmx mod5.cmx

    prog2: $(PROG2_OBJS)
            $(OCAMLOPT) -o prog2 $(OCAMLFLAGS) $(PROG2_OBJS)

    # Common rules
    .SUFFIXES: .ml .mli .cmo .cmi .cmx

    .ml.cmo:
            $(OCAMLC) $(OCAMLFLAGS) -c $<

    .mli.cmi:
            $(OCAMLC) $(OCAMLFLAGS) -c $<

    .ml.cmx:
            $(OCAMLOPT) $(OCAMLOPTFLAGS) -c $<

    # Clean up
    clean:
            rm -f prog1 prog2
            rm -f *.cm[iox]

    # Dependencies
    depend:
            $(OCAMLDEP) $(INCLUDES) *.mli *.ml > .depend

    include .depend