The findlib User's Guide
Prev | Chapter 6. How to create your own packages | Next

# Change your Makefile

Here is a commented version of a Makefile that may be used to compile and link a package. It describes the frequent case that the package simply consists of a bundle of modules that are dependent on other packages.

First, some general definitions. NAME is the name of the package. The OBJECTS variable enumerates the bytecode objects, whereas XOBJECTS names the native objects. The same naming convention is used for ARCHIVE and XARCHIVE, specifying the resulting bytecode, resp. native archive file. The REQUIRES variable lists the names of the packages that are needed for this package. If you need additional predicates, put them into the PREDICATES variable.

    NAME     = p

    OCAMLC   = ocamlfind ocamlc
    OCAMLOPT = ocamlfind ocamlopt
    OCAMLDEP = ocamldep

    OBJECTS  = p1.cmo p2.cmo
    XOBJECTS = p1.cmx p2.cmx

    ARCHIVE  = $(NAME).cma
    XARCHIVE = $(NAME).cmxa

    REQUIRES = unix str q r s
    PREDICATES =

The default goal is "all", causing the bytecode archive to be created. In order to get a native archive, choose "opt" as second goal. (The ".PHONY" line is a declaration meaningful for GNU-make; "all" and "opt" are only virtual goals as there no files "all", or "opt" which is indicated by making them dependents of ".PHONY".)

    .PHONY: all opt
    all: $(ARCHIVE)
    opt: $(XARCHIVE)

The following two rules create the bytecode resp. native archive from the objects.

    $(ARCHIVE): $(OBJECTS)
            $(OCAMLC) -a -o $(ARCHIVE) -package "$(REQUIRES)" -linkpkg \
    	          -predicates "$(PREDICATES)" $(OBJECTS)
    $(XARCHIVE): $(XOBJECTS)
            $(OCAMLOPT) -a -o $(XARCHIVE) -package "$(REQUIRES)" -linkpkg \
    	          -predicates "$(PREDICATES)" $(XOBJECTS)

These rules compile the modules independently. The lines similar to ".ml.cmo" must be read: "How to transform files with suffix .ml into files with suffix .cmo". The corresponding command can refer to the input file as "$<" and to the output file(s) as "$@".

    .SUFFIXES: .cmo .cmi .cmx .ml .mli

    .ml.cmo:
            $(OCAMLC) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \
                      -c $<
    .mli.cmi:
            $(OCAMLC) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \
                      -c $<
    .ml.cmx:
            $(OCAMLOPT) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \
                      -c $<

The "depend" goal is the file describing the dependencies within the package; it is created by ocamldep.

    depend: *.ml *.mli
             $(OCAMLDEP) *.ml *.mli >depend
    include depend

The "install" rule is a bit tricky. First it is tested if there is a native archive to install, and if so, the variable "extra" contains the corresponding files. The "ocamlfind install" command creates a new package directory and puts the given files into it.

    .PHONY: install uninstall
    install: all
             { test ! -f $(XARCHIVE) || extra="$(XARCHIVE) "`basename $(XARCHIVE) .cmxa`.a }; \
    	 ocamlfind install $(NAME) *.mli *.cmi $(ARCHIVE) META $$extra

    uninstall:
             ocamlfind remove $(NAME)

Last but not least a cleanup rule:

    .PHONY: clean
             rm -f *.cmi *.cmo *.cmx *.cma *.cmxa *.a

Prev | Home | Next
How to create your own packages | Up | Using the Makefile wizard