hpc-primer

Make

The make program (several implementation possible, usually the GNU is installed) is a lightweight and portable tool to automate compilation tasks.

Content

Rules 101

Vocabulary

make rules are built around time-stamps and file existence. A rule is triggered if the file targeted does not exists or its timestamp is too old.

Even though targets are not always files (see later), we first assume this is the case

target: prerequisites
    recipe-1
    recipe-2
    recipe-3

Variable

make supports the definition of variables as well as the interaction with environment variables. Unless enforced, the variables work in a verbatim way, meaning that they are not evaluated at creation but at use (the same way a macro would work).

# you can shorten long expressions
VAR1 = /path/to/your/file

# this will replace everywhere VAR2 with ${HOME} and evaluate it at use
VAR2 = ${HOME}

# you can force the evaluation of the variable at creation
VAR3 := ${HOME}

# sets a default value to the variable if not defined
VAR4 ?= ${HOME}

.PHONY targets

make provides a few special targets (see bellow for more details) that help to control the behavior of dependencies. Among them the .PHONY target

.PHONY: target

instructs to make that the target is not associated to a file. The consequence is that everytime the target is called (through make target or as prerequisites) the rule is executed.

Best practice

It is quite common (not mandatory) to have a few phony targets defined in your makefile:

Advanced features

Parallelisation

make can build multiple recipes in parallel. To do so, simply add the option -j N where N is the maximum number of processes. Some user might be tempted to use make -j without specifying a number, which can cause weird behaviors such as signals 2 or 9. I would therefore refrain to do so.

multi(-lines) recipes

There is two ways to handle multi(-line) recipes:

  1. add lines: this will lead to the (maybe parallel and unordered) execution of the recipes. You should also pay attention that every recipe will be executed starting from the location where make has been called.

  2. use the \ and/or && symbols to break lines and introduce dependencies between recipes

Some examples:

# this will work as the recipes are executed both from the same location
my_dir:
    cd /path/to/my_dir
    mkdir -p my_dir

# This will work as a single recipe
my_dir:
    cd /path/to/my_dir && mkdir -p my_dir

# equivalently we can format the recipe over two lines
my_dir:
    cd /path/to/my_dir && \
    mkdir -p my_dir

removing time-stamps

You can remove the time-stamp constrain on the prerequisites and only check for existence using |:

target: file_1 file_2 | file_3
    touch target

Here an up-to-date timestamp for file_1 and file_2 is requested while only the existence of file3 is checked. See here for more information.

Automatic variables

It is very convenient to generalize the recipes using the automatic variables defined automatically by make.

Some are particularly famous:

Match patterns

To automate even further the rules, you can use pattern matching and automatic variables (see bellow). To compile all your .o files you can for example use the following rule:

%.o: %.c
    CXX $^ -o $@

Special targets

Special targets can be used to further fine-tune the behavior of make.

Functions

make also comes with convenient functions:


home - compilation