All notes
Mak

Template

Recipes

Ref.

Ignore errors

To ignore errors in a recipe line, write a '-' at the beginning of the line's text (after the initial tab). The '-' is discarded before the line is passed to the shell for execution.

For example,

clean:
	-rm -f *.o
This causes make to continue even if rm is unable to remove a file.
When you run make with the '-i' or '--ignore-errors' flag, errors are ignored in all recipes of all rules. A rule in the makefile for the special target .IGNORE has the same effect, if there are no prerequisites. These ways of ignoring errors are obsolete because '-' is more flexible.

Echoing

Writing Makefiles

Include

The include directive tells make to suspend reading the current makefile and read one or more other makefiles before continuing.

filenames can contain shell file name patterns.


include foo *.mk $(bar)

# Simply ignore a makefile which does not exist or cannot be remade, with no error message
-include filenames

If the specified name does not start with a slash, the included files are search in order under:

  1. Current directory
  2. Dirs specified with the ‘-I’ or ‘--include-dir’ option
  3. In order: prefix/include (normally /usr/local/include) /usr/gnu/include, /usr/local/include, /usr/include.

Occasions for using include directives:

Remake Makefiles

Sometimes makefiles can be remade from other files, such as RCS or SCCS files.

Writing Rules

Automatic Prerequisites

For example, if main.c uses defs.h via an #include, you would write:


main.o: defs.h

Most modern C compilers can write these rules for you, by looking at the #include lines in the source files:


cc -M main.c
# generates the output:
# main.o : main.c defs.h

With old make programs, it was traditional practice to use this compiler feature to generate prerequisites on demand with a command like make depend.
That command would create a file depend containing all the automatically-generated prerequisites; then the makefile could use include to read them in.

GNU make remaking

In GNU make, the feature of remaking makefiles makes this practice obsolete — you need never tell make explicitly to regenerate the prerequisites.

For each source file name.c there is a makefile name.d which lists what files the object file name.o depends on. Here is the rule to make name.d:


%.d: %.c
	@set -e; rm -f [email protected]; \
	 $(CC) -M $(CPPFLAGS) $< > [email protected]$$$$; \
	 sed 's,\($*\)\.o[ :]*,.o [email protected] : ,g' < [email protected]$$$$ > [email protected]; \
	 rm -f [email protected]$$$$

sources = foo.c bar.c
# NOTE: Place the include directive after the first, default goal, or it will become the default.
include $(sources:.c=.d)

Run make

Arguments to Specify the Makefile

the default is to try GNUmakefile, makefile, and Makefile, in order.

Commands

Strings

Ref.

$(subst from,to,text)
	Each occurrence of from is replaced by to from text.
$(subst ee,EE,feet on the street)
	substitutes the string `fEEt on the strEEt'.

$(patsubst pattern,replacement,text)
$(patsubst %.c,%.o,x.c.c bar.c)
	produces the value `x.c.o bar.o'

$(var:pattern=replacement)
is equivalent to
$(patsubst pattern,replacement,$(var))

$(var:suffix=replacement)
is equivalent to
$(patsubst %suffix,%replacement,$(var))

objects = foo.o bar.o baz.o
$(objects:.o=.c)
	Get the list of corresponding source files.

Variables

Target-specific Variable Values

target ... : variable-assignment

prog : CFLAGS = -g
prog : prog.o foo.o bar.o
	will set CFLAGS to '-g' in the recipe for prog, but it will also set CFLAGS to '-g' in the recipes that create prog.o, foo.o, and bar.o, and any recipes which create their prerequisites.

[email protected] The name of the target file (the one before the colon)
$< The name of the first (or only) prerequisite file (the first one after the colon)
$^ The names of all the prerequisite files (space separated)
$* The stem (the bit which matches the % wildcard in the rule definition.

Set variable at make command line

Ref. make can take variable assignments as part of his command line, mingled with targets:

make target FOO=bar
But then all assignments to FOO variable within the makefile will be ignored unless you use the override directive in assignment. (The effect is the same as with -e option for environment variables).

Environment variables. It is recommended to use the conditional variable assignment operator, which only has an effect if the variable is not yet defined:

FOO?=default_value_if_not_set_in_environment

Functions

origin

GNU.org: origin function.

$(origin variable)

# If bletch has been defined from the environment, this will redefine it.
ifdef bletch
  ifeq "$(origin bletch)" "environment"
    bletch = barf, gag, etc.
  endif
endif

Return values:

FAQ

Pass variable in command-line

StackOverflow: passing additional var from commandline to make.

1. Each environment variable is transformed into a makefile variable with the same name and value.

2. From command line: make target Foo=bar.
It will overwrite all assignments to FOO variable within the makefile. Same as "-e" option in environment variable.
To pass from command line somthing with spaces do make A='"as df"'.

3. From parent Makefile:

CFLAGS=-g
# Export.
export CFLAGS

target:
	$(MAKE) -C target
You can also export all variables by using export without arguments.

Just based on experience, exporting stuff like CFLAGS is a recipe for nightmare for large projects. Large projects often have 3rd party libraries that only compile with a given set of flags (that no one bothers fixing). If you export CFLAGS, your project's CFLAGS ends up overriding the 3rd party library's and triggers compile errors.
An alternate way might be to define export PROJECT_MAKE_ARGS = CC=$(CC) CFLAGS=$(CFLAGS) and pass it along as make -C folder $(PROJECT_MAKE_FLAGS).
If there's a way to tell the library's makefile to ignore the environment, that'd be ideal (opposite of -e).