I have the following in my GNU makefile:
# CXXFLAGS ?= -DNDEBUG -g2 -O3
CXXFLAGS ?=
# Add -DNDEBUG if nothing specified
ifeq ($(filter -DDEBUG -DNDEBUG,$(CXXFLAGS)),)
$(info Adding -DNDEBUG to CXXFLAGS)
CXXFLAGS += -DNDEBUG
endif
# Add a symolize if nothing specified
ifeq ($(filter -g -g1 -g2 -g3 -Oz,$(CXXFLAGS)),)
$(info Adding -g2 to CXXFLAGS)
CXXFLAGS += -g2
endif
# Add an optimize if nothing specified
$(info Adding -O3 to CXXFLAGS)
ifeq ($(filter -O -O0 -O1 -O2 -O3 -Og -Os -Oz -Ofast,$(CXXFLAGS)),)
CXXFLAGS += -O3
endif
When I run it:
$ make CXXFLAGS="-g3"
Adding -DNDEBUG to CXXFLAGS
Adding -O3 to CXXFLAGS
g++ -g3 -c foo.cpp
...
In fact, if I uncomment the CXXFLAGS ?= -DNDEBUG ..., then I can append again. But that's not very helpful since I'm trying to make arguments optional (but with sane defaults).
And if I type just make, then it works (-fPIC -march=native -Wall -Wextra -pipe is added later by the same makefile, and it has always worked):
$ make
Adding -DNDEBUG to CXXFLAGS
Adding -g2 to CXXFLAGS
Adding -O3 to CXXFLAGS
g++ -DNDEBUG -g2 -O3 -fPIC -march=native -Wall -Wextra -pipe -c serpent.cpp
...
According to the manual and 6.6 Appending More Text to Variables:
Often it is useful to add more text to the value of a variable already defined. You do this with a line containing ‘+=’, like this:
objects += another.o
Why is make not adding the values to the variable? How can I achieve the behavior I want?
By passing a variable via command-line, you're telling make that you are overriding any definitions in the file, which allows a user to compile as they intend rather than as you intend. Ignoring the restriction of user freedom, you can use the override directive:
To append more text to a variable defined on the command line, use:
override variable += more text
Variable assignments marked with the override flag have a higher priority
than all other assignments, except another override. Subsequent
assignments or appends to this variable which are not marked override
will be ignored.
I would discourage you from using override when possible because it's annoying to realize that -O0 was needed to disable the optimizations that you enabled when I don't want them enabled (after all, I specify my own flags for a reason). Of course, if no flags were specified at all, then defaults are perfectly reasonable. In fact, Automake projects seem to default to -g -O2 when no compilation flags are specified.
There are exceptions to this advice of course, such as adding a directory to search for includes/libs or preprocessor definitions for compiling a conditional section of code on a certain platform.
Related
Here is my simple Makefile. I am trying to set the C macro "GIT_COMMIT" in my Makefile and pass it to the C program.
all: control
control: control.cpp serial_port.cpp
GIT_COMMIT=5
g++ -g -DGIT_COMMIT=$(GIT_COMMIT) -Wall $^ -o control -lpthread
Unfortunately, when I run make, I see this and make is completely ignoring my GIT_COMMIT variable. What am I doing wrong? Thanks.
GIT_COMMIT=5
g++ -g -DGIT_COMMIT= -Wall control.cpp serial_port.cpp -o control -lpthread
placing the setting of GIT_COMMIT as an action inside the 'control' rule will, as you discovered, not work to produce a macro. suggest:
all: control
GIT_COMMIT := 5
control: control.cpp serial_port.cpp
g++ -g -DGIT_COMMIT=$(GIT_COMMIT) -Wall $^ -o control -lpthread
I have a simple gnu makefile:
ifdef $(DEBUGGING)
CFLAGS = -g -O0 -Wall
else
CFLAGS = -O3 -Wall
endif
test:
#echo DEBUGGING is $(DEBUGGING)
#echo $(CFLAGS)
When I invoke it like this, I see that DEBUGGING is set to true, but ifdef $DEBUGGING appears to be false:
$ DEBUGGING=true make test
DEBUGGING is true
-O3 -Wall
I would expect that CFLAGS would be set to "-g -O0 -Wall". What am I missing?
You use the NAME of the variable in the ifdef:
ifdef DEBUGGING
The value given to ifdef is expanded first, and the result is considered a variable name.
The project that I am trying to build has default flags
CFLAGS = -Wall -g -O2
CXXFLAGS = -g -O2
I need to append a flag -w to both these variables (to remove: 'consider all warnings as errors')
I have a method to work it out, give
make 'CFLAGS=-Wall -g -O2 -w'; 'CXXFLAGS=-g -O2 -w'
OR
Run ./configure and statically modify Makefile
But I want to append my options with the existing options while running configure or make
The post
Where to add a CFLAG, such as -std=gnu99, into an autotools project
conveniently uses a macro to achieve this.
You almost have it right; why did you add the semicolon?
To do it on the configure line:
./configure CFLAGS='-g -O2 -w' CXXFLAGS='-g -O2 -w'
To do it on the make line:
make CFLAGS='-g -O2 -w' CXXFLAGS='-g -O2 -w'
However, that doesn't really remove consider all warnings as errors; that removes all warnings. So specifying both -Wall and -w doesn't make sense. If you want to keep the warnings but not have them considered errors, use the -Wall -Wno-error flags.
Alternatively, most configure scripts which enable -Werror by default also have a flag such as --disable-werror or similar. Run ./configure --help and see if there's something like that.
I am trying to run program from the Learn C Hard Way book
I need to pass the library filename 'build/liblcthw.a' as the last parameter.
For eg :
Doesnt Work on Ubuntu :
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG build/liblcthw.a tests/list_tests.c -o tests/list_tests
Works on Ubuntu :
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG tests/list_tests.c -o tests/list_tests build/liblcthw.a
How do I handle this in Makefile ? CFLAGS will only add it before the source filename and it doesnt work. How do I force CFALGS to add the library filename at the end of the command ?
CFLAGS are flags for the C compiler. Libraries typically go into a variable called LDLIBS. Set LDLIBS=build/liblcthw.a and see if that works.
The first invocation doesn't succeed because the order of sources and libraries in the command line is wrong. The correct order is source files, then object files, followed by static libraries followed by dynamic libraries.
In a Makefile of a library I am trying to build, there are a few lines specify the options to gcc:
CFLAGS += -I$(CURDIR) -pedantic -std=c89 -O3
CFLAGS += -Wall -Wno-unused-function -Wno-long-long
CFLAGS += $(if $(DEBUG), -O0 -g)
If DEBUG exists, there will be both -O3 and -O0 -g in CFLAGS. But -O0 and -O3 cannot be used at the same time. Will the one specified later supersede the one earlier?
Thanks and regards!
From the manpage:
If you use multiple -O options, with or without level numbers, the
last such option is the one that is effective.