Definition
From Setting Variables in the docs:
- Use as
=,:=, or::=and a value. - White space is ignored.
Plain definition
FOO =
CXX = g++
objects = main.o foo.o bar.o utils.o
SHELL = /bin/bash
JS_DIR = assets/js
You don’t need quotes around multiple words.
You can define a value referencing another variable, including user input.
FOO = abc
Note lack of colon here. So expansion is deferred, such that $(FOO) is evaluated when BAR is used, rather than immediately. It reflects the latest value so can change.
BAR = $(FOO)
Evaluation
Note colon and equals sign here.
Variable
Simple expanded variable, evaluated immediately and fixed at definition time.
BAR := $(FOO)
shell
Using := $(shell ...) syntax:
hash := $(shell printf '\043')
var := $(shell find . -name "*.c")
if
Using a Make if statement.
BUZZ := $(if $(FOO), 'abc', $(FIZZ))
not equal
Using != ... syntax:
If the result of the execution could produce a
$, and you don’t intend what follows that to be interpreted as amakevariable or function reference, then you must replace every$with$$as part of the execution.
hash != printf '\043'
file_list != find . -name '*.c'
Default value
Here are two equivalent ways to set a variable if it is not defined.
FOO ?= bar
Or
ifeq ($(origin FOO), undefined)
FOO = bar
endif
User input with a default value
Use the ?= syntax to set a Make variable with a default value which can be overridden by the user.
Code:
Makefilename ?= World greet: @echo "Hello, $(name)!"
Usage:
$ make greet
Hello, World!
$ make greet name=dev
Hello, dev!
Note that variable names are case-sensitive - so make sure what you pass in on the shell matches what is in the Makefile.
See Parameters section on passing variables.
Export variables
How to let Make variables be accessible to subprocesses.
The Make variables are always accessible as Make variables.
ENV = dev
foo:
echo $(ENV)
But variables are not accessible in Shell commands, unless you use Make’s export prefix.
export ENV = dev
foo:
echo $$ENV
Using export within a target does not work, as variables are not persisted between commands in a target. So don’t do this:
test:
export ENV=dev
bash -c 'echo $$ENV'
But you can use like this. Here we simulate a command using ENV by doing an echo inside a subshell.
test:
ENV=dev bash -c 'echo $$ENV'
# More verbose alternative.
export ENV=dev && bash -c 'echo $$ENV'