All notes
Mak

# 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

• When a line starts with '@', the echoing of that line is suppressed.
• When make is given the flag '-n' or '--just-print' it only echoes most recipes, without executing them.
• The '-s' or '--silent' flag to make prevents all echoing, as if all recipes started with '@'.
• A rule in the makefile for the special target .SILENT without prerequisites has the same effect (see Special Built-in Target Names). .SILENT is essentially obsolete since '@' is more flexible.

# 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: • Several programs, handled by individual makefiles in various directories, need to use a common set of variable definitions or pattern rules. • Generate prerequisites from source files automatically; the prerequisites can be put in a file that is included by the main makefile. ## 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) • The ‘-e’ flag to the shell causes it to exit immediately if the CC command (or any other command) fails (exits with a nonzero status). • With GNU C compiler, use the ‘-MM’ flag instead of ‘-M’. This omits prerequisites on system header files. • The sed command is to translate "main.o : main.c defs.h" into "main.o main.d : main.c defs.h" # 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   $(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: • undefined: if variable was never defined. • default: if variable has a default definition, as is usual with CC and so on. See Variables Used by Implicit Rules. Note that if you have redefined a default variable, the origin function will return the origin of the later definition. • environment: if variable was inherited from the environment provided to make. • environment override: if variable was inherited from the environment provided to make, and is overriding a setting for variable in the makefile as a result of the '-e' option (see Summary of Options). • file: if variable was defined in a makefile. • command line: if variable was defined on the command line. • override: if variable was defined with an override directive in a makefile (see The override Directive). • automatic: if variable is an automatic variable defined for the execution of the recipe for each rule (see Automatic Variables). # FAQ ## Pass variable in command-line 1. Each environment variable is transformed into a makefile variable with the same name and value. • Only if "-e" option (aka "--environments-override") is on, your environment variables will override assignments made into makefile, unless these assignments themselves use the override directive. • It's much better and flexible to use "?=" assignment (the conditional variable assignment operator, which only has an effect if the variable is not yet defined). • Note that certain variables are not inherited from environment: MAKE, SHELL. 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).