Variables and Environment
The Hierarchy of Variable Precedence
-
The
overrideDirective (Inside Makefile)Syntax:
override CFLAGS += -g -
Command-Line Arguments
Syntax:
make CFLAGS = -O2 -
Makefile Assignments (Normal)
Syntax:
CFLAGS = -O2 -
Environment Variables:
Variables exported in your shell before running make.
Make imports these automatically but lets the Makefile overwrite them.
Syntax:
export CFLAGS=-O2 -
The
conditionalDirective (?=)Only assigns a value if the variable is currently undefined.
Syntax:
CFLAGS ?= -g -
Implicit / Built-in Variables
Default values baked into Make (e.g.,
CCdefaults tocc)
Automatic Variables
Nuances about $?
$? lists prerequisites that are strictly newer than the target.
Gotcha: If the target doesn't exist yet, Make considers its timestamp to be "infinitely old." Therefore, Make assumes every single prerequisite is "newer" than the non-existent target, and $? will list all of them.
Behaviours that are different between Shell and Make
Referencing Variables
-
Make: Without parentheses or braces, Make only reads the very next character.
-
Shell:
The shell sees
$then keeps reading until it hits a character that cannot be part of a variable name.When do you need them in Shell?
They are only strictly required when you need to disambiguate the variable name from the surrounding text. (
${path}_v1)NOTICE: Only
{}works in shell for this purpose,()doesn't mean this!!
Make Variables vs Shell Variables
-
Make Variables
Defined at the start of a line (no indentation, Top-level).
Spaces around the assignment operator
=are allowed. -
Shell Variables
Inside a recipe (Indented with Tab). (NO SPACES around
=)
Things related to $
If you need a literal $(var) to appear in a file generated by a shell command inside a Makefile, you usually need \$$ (Backslash + Double Dollar).
Remember you are passing a string through three different parsers, and each one wants to eat your dollar signs.
About spaces
Since Make automatically strips away the leading spaces in assignment, to create a variable that contains leading spaces, you will need to use some tricks.
The steps are as follows:
-
Create a space character using an empty
nullstringvariable. -
Create variables that have leading spaces using the space character created.
-
When trying to print out these variables, even if the variables created in Step 2 do contain spaces, Make will expand the variable and hand this command to the shell, which eats the spaces.
By default, the shell treats any amount of unquoted whitespace as a delimiter separating arguments.
To force the shell to respect the whitespace exactly as Make expands it, you need to wrap the variable in double quotes inside your
echocommand.For example:
Spaces are allowed in the following specific places.
1. Around the = sign in assignments:
2. Between Targets and Prerequisites:
3. Inside Line Continuations:
# Valid. The backslash escapes the newline, and the indentation
# on the next line is usually ignored (unless it's in a recipe).
SRCS = main.c \
utils.c \
api.c
The += Operator
The += operator won't cause the problems which normally appending to recursive variables cause.