Go to the first, previous, next, last section, table of contents.
To get started, let us look at the `Makefile' for an imaginary small
`fptools' project, `small'. Each project in `fptools' has its own
directory in `FPTOOLS_TOP', so the `small' project will have its own
directory `FPOOLS_TOP/small/'. Inside the `small/' directory there
will be a `Makefile', looking something like this:
# Makefile for fptools project "small"
TOP = ..
include $(TOP)/mk/boilerplate.mk
SRCS = $(wildcard *.lhs) $(wildcard *.c)
HS_PROG = small
include $(TOP)/target.mk
This `Makefile' has three sections:
-
The first section includes(1)
a file of "boilerplate" code from the
level above (which in this case will be `FPTOOLS_TOP/mk/boilerplate.mk').
As its name suggests, `boilerplate.mk' consists of a large quantity of standard
`Makefile' code. We discuss this boilerplate in more detail in Section See section The main `mk/boilerplate.mk' file.
Before the `include' statement, you must define the `make' variable
`TOP' to be the directory containing the `mk' directory in which
the `boilerplate.mk' file is.
It is not OK to simply say
include ../mk/boilerplate.mk # NO NO NO
Why? Because the `boilerplate.mk' file needs to know where it is,
so that it can, in turn, `include' other files.
(Unfortunately, when an `include'd file does an
`include', the filename is treated
relative to the directory in which `gmake' is being run, not
the directory in which the `included' sits.)
In general,
every file `foo.mk'
assumes that `$(TOP)/mk/foo.mk' refers to itself.
It is up to the `Makefile' doing the `include' to ensure this
is the case.
Files intended for inclusion in other `Makefile's are written to have
the following property:
after `foo.mk' is `include'd, it leaves `TOP' containing the same
value as it had just before the `include' statement.
In our example, this invariant guarantees that the `include'
for `target.mk' will look in the same directory as that for
`boilerplate.mk'.
-
The second section
defines the following standard `make' variables: `SRCS' (the source files from
which is to be built), and `HS_PROG' (the
executable binary to be built).
We will discuss in more detail what the "standard variables" are,
and how they affect what happens, in Section See section The main `mk/target.mk' file.
The definition for `SRCS' uses the useful GNU `make'
construct `$(wildcard' pat`)', which expands to a list of all the
files matching the pattern pat in the current directory.
In this example, `SRCS' is set to the list of all the `.lhs' and `.c' files
in the directory. (Let's suppose there is one of each, `Foo.lhs'
and `Baz.c'.)
-
The last section includes a second file of standard code,
called `target.mk'. It contains the rules that tell `gmake'
how to make the standard targets
(Section See section Standard targets).
Why, you ask, can't this standard code
be part of `boilerplate.mk'? Good question.
We discuss the reason later, in Section See section Boilerplate architecture.
You do not have to `include' the `target.mk' file. Instead,
you can write rules of your own for all the standard targets.
Usually, though, you will find quite a big payoff from using
the canned rules in
`target.mk'; the price tag is that you have to understand
what canned rules get enabled, and what they do (Section See section The main `mk/target.mk' file).
In our example `Makefile', most of the work is done
by the two `include'd files. When you say `gmake all',
the following things happen:
-
`gmake' figures out that the object files are `Foo.o' and `Baz.o'.
-
It uses a boilerplate pattern rule to compile
`Foo.lhs' to `Foo.o' using
a Haskell compiler. (Which one? That is set in the build configuration.)
-
It uses another standard pattern rule to compile `Baz.c' to `Baz.o',
using a C compiler. (Ditto.)
-
It links the resulting `.o' files together to make `small',
using the Haskell compiler to do the link step. (Why not use `ld'? Because
the Haskell compiler knows what standard librarise to link in. How did `gmake'
know to use the Haskell compiler to do the link, rather than the C compiler?
Because we set the variable `HS_PROG' rather than `C_PROG'.)
All `Makefile's should follow the above three-section format.
Go to the first, previous, next, last section, table of contents.