Append to GNU make variables via command line

2020-01-30 05:35发布

问题:

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?

回答1:

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 


回答2:

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)


回答3:

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.



回答4:

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.