How to change default values of variables like CC in Makefile

(GNU) make uses several variables like:

I would like to specify my own default values of some of them in my Makefile. In the example below I used the conditional assignment operator ?= to be able to override my defaults when running make:

CFLAGS ?= CFLAGS_my_default
CC ?= CC_my_default

print:
    echo CC=$(CC) CFLAGS=$(CFLAGS)

Unfortunately this does not change the value of the CC variable as the original default value stays there. CFLAGS are set by my assignment as the variable was originally empty:

$ make print
echo CC=cc CFLAGS=CFLAGS_my_default
CC=cc CFLAGS=CFLAGS_my_default

Overriding from environment variables works as expected:

$ CC=CC_from_env CFLAGS=CFLAGS_from_env make print
echo CC=CC_from_env CFLAGS=CFLAGS_from_env
CC=CC_from_env CFLAGS=CFLAGS_from_env

How can I change the default values of variables and still be able to override them when invoking make?

Upvotes: 29

Views: 21770

Answers (2)

jmlemetayer
jmlemetayer

Reputation: 4952

I have used this Makefile to run some tests with GNU Make and check the origin and default value of some variables:

define whatisit
$(info $(1) origin is ($(origin $(1))) and value is ($($(1))))
endef

$(call whatisit,CC)
$(call whatisit,CFLAGS)

Here are the results:

$ make
CC origin is (default) and value is (cc)
CFLAGS origin is (undefined) and value is ()
$ # Environment
$ CC=clang CFLAGS=-Wall make
CC origin is (environment) and value is (clang)
CFLAGS origin is (environment) and value is (-Wall)
$ # Command line
$ make CC=clang CFLAGS=-Wall
CC origin is (command line) and value is (clang)
CFLAGS origin is (command line) and value is (-Wall)

As you can see there is two types of variables. These types are defined in the manual.

The first set of variables (AR, AS, CC, ...) have default values. The second set of variables (ARFLAGS, ASFLAGS, CFLAGS, ...) are default to an empty string (i.e. undefined).

By default, they can be override by environment or command line.


Set default value for the undefined variables

For the undefined variables (and also other user variables) you just have to use the ?= operator to set a default value which can be override by environment or command line.

CFLAGS ?= -Wall -Wextra -Werror

Set default value for the default variables

The best way to change default value for the default variables is to check for their origin and change the value only when it is needed.

ifeq ($(origin CC),default)
CC = gcc
endif

Conclusion

The Makefile:

ifeq ($(origin CC),default)
CC  = gcc
endif
CFLAGS  ?= -Wall -Wextra -Werror

define whatisit
$(info $(1) origin is ($(origin $(1))) and value is ($($(1))))
endef

$(call whatisit,CC)
$(call whatisit,CFLAGS)

The final result:

$ make
CC origin is (file) and value is (gcc)
CFLAGS origin is (file) and value is (-Wall -Wextra -Werror)
$ # Environment
$ CC=clang CFLAGS=-Wall make
CC origin is (environment) and value is (clang)
CFLAGS origin is (environment) and value is (-Wall)
$ # Command line
$ make CC=clang CFLAGS=-Wall
CC origin is (command line) and value is (clang)
CFLAGS origin is (command line) and value is (-Wall)

Optional

You can use the MAKEFLAGS variable to disable the built-in implicit rules and the built-in variable settings. This way:

MAKEFLAGS += -rR

This will clean a lot of default settings (you can check it by using make -p). But the default variables (like CC) will still have a default value.

Upvotes: 15

It is possible to use non-conditional assignment:

CFLAGS ?= CFLAGS_my_default
CC = CC_my_default

print:
    echo CC=$(CC) CFLAGS=$(CFLAGS)

but unconditionally set variables cannot be overridden from environment variables:

$ CC=CC_from_env CFLAGS=CFLAGS_from_env make print
echo CC=CC_my_default CFLAGS=CFLAGS_from_env
CC=CC_my_default CFLAGS=CFLAGS_from_env

Wait, there is another way of setting the variable when invoking make! - from command-line arguments:

$ make print CC=CC_from_cmdline CFLAGS=CFLAGS_from_cmdline
echo CC=CC_from_cmdline CFLAGS=CFLAGS_from_cmdline
CC=CC_from_cmdline CFLAGS=CFLAGS_from_cmdline

This way the non-conditionally set variables get overridden too. This method even works with recursive use of make where the variables specified on command-line are automatically passed to the new make process.

Another method is to enable overriding of unconditionally set variables by environment variables using command switch -e:

$ CC=CC_from_env CFLAGS=CFLAGS_from_env make -e print
echo CC=CC_from_env CFLAGS=CFLAGS_from_env
CC=CC_from_env CFLAGS=CFLAGS_from_env

Upvotes: 11

Related Questions