I am using a GNU-make Makefile to build a C project with several targets (all
, clean
, and a few project specific targets). In the process of debugging, I would like to append some flags to a single build without permanently editing the Makefile (e.g. add debugging symbols or set a preprocessor flag).
In the past, I have done that as follows (using the debugging symbols example):
make target CFLAGS+=-g
Unfortunately, this is not appending to the CFLAGS
variable, but instead, clearing it and stopping it from compiling. Is there a clean way of doing this without defining some sort of dummy variable appended to the end of CFLAGS
and LDFLAGS
?
Check out the override directive. You will probably need to modify the makefile once, but it should do what you want.
Example makefile:
override CFLAGS += -Wall
app: main.c
gcc $(CFLAGS) -o app main.c
Example command lines:
$ make
gcc -Wall -o app main.c
$ make CFLAGS=-g
gcc -g -Wall -o app main.c
For the record, @Carl Norum's answer prepends the variable, from the command line perspective.
I needed a way to actually append and came up with:
override CFLAGS := -Wall $(CFLAGS)
There are two ways to pass variables to make:
Using command line arguments: make VAR=value
Using environment: export VAR=var; make or (better because it change environment only for current command) VAR=var make
They are slightly different. The first one is stronger. It mean you know what you want. The second may be considered like a hint. Difference between them is about operators =
and +=
(without override
). These operators are ignored when a variable is defined on command line, but are not ignored when variable is defined in environment. Thus, I suggest you to have a Makefile with:
CC ?= gcc
CFLAGS += -Wall
INTERNAL_VARS = value
and call it with:
CFLAGS=-g make
Notice, if you want to withdraw -Wall
, you can use:
make CFLAGS=
Please don't use override
keyword, else you won't have any way to change a variable affected with override
.
Just a note, as I got confused - let this be file testmake
:
$(eval $(info A: CFLAGS here is $(CFLAGS)))
override CFLAGS += -B
$(eval $(info B: CFLAGS here is $(CFLAGS)))
CFLAGS += -C
$(eval $(info C: CFLAGS here is $(CFLAGS)))
override CFLAGS += -D
$(eval $(info D: CFLAGS here is $(CFLAGS)))
CFLAGS += -E
$(eval $(info E: CFLAGS here is $(CFLAGS)))
Then:
$ make -f testmake
A: CFLAGS here is
B: CFLAGS here is -B
C: CFLAGS here is -B
D: CFLAGS here is -B -D
E: CFLAGS here is -B -D
make: *** No targets. Stop.
$ make -f testmake CFLAGS+=-g
A: CFLAGS here is -g
B: CFLAGS here is -g -B
C: CFLAGS here is -g -B
D: CFLAGS here is -g -B -D
E: CFLAGS here is -g -B -D
make: *** No targets. Stop.
With the override
directives deleted from the testmake
file:
$ make -f testmake
A: CFLAGS here is
B: CFLAGS here is -B
C: CFLAGS here is -B -C
D: CFLAGS here is -B -C -D
E: CFLAGS here is -B -C -D -E
make: *** No targets. Stop.
$ make -f testmake CFLAGS+=-g
A: CFLAGS here is -g
B: CFLAGS here is -g
C: CFLAGS here is -g
D: CFLAGS here is -g
E: CFLAGS here is -g
make: *** No targets. Stop.
So,
if a variable used override once, it can only be appended with another statement with override (the normal assignments will be ignored);
when there's been no override at all; trying to append (as in +=) from the command line overwrites every instance of that variable.
Success story sharing