what do the compiler options mean? and '?'followed by '=-03' - makefile

/redis/deps/hiredis/Makefile
CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
OPTIMIZATION?=-O3
WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings
DEBUG?= -g -ggdb
what do the complier options mean? and '?'followed by '=-03'?

for OPTIMIZATION?=-O3
If the variable OPTIMIZATION has NOT been defined, OPTIMIZATION is valued as -O3;
On the other side, if the variable OPTIMIZATION has been defined, this statement will be skipped, and OPTIMIZATION will keep its previous value

The GNU make manual has this text for the ?= operator
There is another assignment operator for variables, ‘?=’. This is
called a conditional variable assignment operator, because it only has
an effect if the variable is not yet defined.
So, this statement
OPTIMIZATION?=-O3
says that if OPTIMIZATION has been defined, ignore it and if not, define it and assign a value -03.
The -03 as compiler flags means compile at optimization level 3.

Related

Is gcc flags repetition and ordering important?

I see some of gcc flags repeated when building C extension for python. When I run:
python setup.py build_ext
The running build command looks like this:
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -march=x86-64 -mtune=generic -O3 -pipe -fstack-protector-strong -fno-plt -flto=4 -fuse-linker-plugin -ffat-lto-objects -flto-partition=none -march=x86-64 -mtune=generic -O3 -pipe -fstack-protector-strong -fno-plt -march=x86-64 -mtune=generic -O3 -pipe -fstack-protector-strong -fno-plt -fPIC -I/usr/include/python3.7m -c /tmp/src/source.c -o build/temp.linux-x86_64-3.7/tmp/src/source.o
gcc -pthread -shared -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -flto=4 -fuse-linker-plugin -ffat-lto-objects -flto-partition=none -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now build/temp.linux-x86_64-3.7/tmp/src/source.o -L/usr/lib -lpython3.7m -o build/lib.linux-x86_64-3.7/source.cpython-37m-x86_64-linux-gnu.so
Ok, that's a long one. But, as you can see some flags are repeated. Here is the repetition in the first command:
-O3 repeated 4 times.
-fno-plt repeated 3 times.
-fstack-protector-strong repeated 3 times.
-march=x86-64 repeated 3 times.
-mtune=generic repeated 3 times.
-pipe repeated 3 times.
Beside -Wl,... flags which are passed to linker, does those flags repetition and ordering have any meanings?
It's not unusual to see repetitions of options in GCC commandlines
that have been generated by some tool-stack (frequently an IDE), with
human input "at the top".
None of the repetitions you have spotted makes any difference to the
meaning of the commandline. Usually such repetitions just amount to innocuous
redundancy, and they can have a rational
motive. A tool that is adding something incrementally to a GCC commandline may
wish to ensure that a certain option is in enabled at that point, even if it
might have been somehow disabled by an option appended since the last occurrence that enabled it. Repeating
the option redundantly may be cheaper than checking whether it is redundant.
But repetition is not necessarily innocuous...
If an option OPT occurs at some point in the commandline:
... OPT ...
then replacing that one occurrence with 2 or more will not make a difference.
However, if the commandline is of the form:
... OPT1 ... OPT2 ...
Then adding another occurrence of OPT1 anywhere after OPT2 may well make a
difference. Likewise adding another occurrence of OPT2 anywhere before OPT1.
That is because the order in which options occur very often makes a
difference.
An option is routinely composed of a flag and a value, e.g
-O3 -> Flag = -O, value = 3
-I./inc -> Flag = -I, value = ../inc
Some flags, like -O can take any one of a set of mutually
exclusive values. Call these mutex flags, for short. When a mutex flag occurs repeatedly with
countervailing values, the last in the commandline prevails:
-O1 -O2 -O3 = -O3
-O3 -O2 -O1 = -O1
Others flags, like -I, can take arbitary
non-exclusive values successively that are accumulated, in their order of occurrence, to form a sequence that
is one of the parameters of compilation or linkage. E.g.
-I./foo -I./bar
appends ./foo and then ./bar to the user-specified include-directory
search order for compilation. Call these cumulative flags.
Other flags are boolean and have an enabling form and a disabling
form , e.g. -fstack-protector,
-fno-stack-protector. These can be equated to mutex options with
exclusive possible values True and False.
And yet another kind of flag, like -l, accepts arbitrary non-exclusive values
successively that are not accumulated, but each just becomes the value of the flag
at that point in the commandline. For all I can recall, -l is the only flag of this kind,
which is an anomalous kind: -lfoo isn't really an option so much as a positional argument
to which the flag attaches a method of interpretation. It says that a file
libfoo.{so|a} is to be input to the linkage at this point, whose absolute pathname
the linker is to discover algorithmically (with reference to the -L options). Let's
call such flags positional flags.
For mutex flags, the meaning of a commandline can be changed if an option
occurring somewhere is repeated later. E.g.
-fno-stack-protector -O1 -O3 -fstack-protector
already looks as if too many cooks have been spoiling the broth, and
is equivalent to:
-O3 -fstack-protector
But if we append some repetition:
-fno-stack-protector -O1 -O3 -fstack-protector -fno-stack-protector -O1
it becomes equivalent to:
-O1 -fno-stack-protector
For cumulative flags, it's easier to envisage messing with the meaning
of the commandline by repeating an option before some occurrence than after:
-I./foo -I./bar
means what it says. Whereas
-I./bar -I./foo -I./bar
means the same as:
-I./bar -I./foo
But that sort of messing hardly happens in practice, because repetitions of
options are almost always generated by appending
a repetition to a commandline during incremental construction.
Positional flags are by definition sensitive to order, both amongst themselves
and in relation to other options and positional arguments. Every permutation of
... -lfoo -lbar main.o ...
yields a different linkage. And repetition of options with positional flags
can also easily make a difference. Notoriously,
... -lfoo main.o ...
may well result in a linkage failure, which
... -lfoo main.o -lfoo
would fix.
So emphatically, yes, repetition and ordering of flags can be important.

How to hide print information of Makefile?

when Makefile execute some tasks, il will print many information in console, can we choose to hide them? when I have many .o to generate, these information will be too many to see and they are just meaningless if we don't read them.
The following code
$(obj)environment.o: $(src)environment.c
$(CC) $(AFLAGS) -Wa, --no-warn \
-DENV_CRC=$(shell $(obj)../tools/envcrc) \
-c -o $# $(src)environment.c
will print heavy information like
arm-linux-gcc -g -Os -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float
-D__KERNEL__ -DTEXT_BASE=0x01000000
-I/home/mingzhao/Documents/bootloader/u-boot-1.2.0/include
-fno-builtin -ffreestanding -nostdinc -isystem
/home/mingzhao/Documents/bootloader/arm/4.3.2/bin/../lib/
gcc/arm-none-linux-gnueabi/4.3.2/include -pipe -DCONFIG_ARM
-D__ARM__ -march=armv4 -mabi=apcs-gnu -Wall -Wstrict-prototypes
-c -o environment.o environment.c
The "right" way to handle this (IMO) is to add this to your makefile:
$(VERBOSE).SILENT:
Then in your rules where you don't ever want the command printed (for example, an echo statement as in Beta's answer below) you prefix it with #. For all other commands, you don't prefix it with #.
What this does is enable "silent" mode by default (because the variable VERBOSE is not set and so this resolves to the .SILENT pseudo-target).
Then if you want to see everything, you add a VERBOSE=1 (actually you can set it to any non-empty value, so VERBOSE=true if you prefer). When you do that it turns off "silent" mode because the above line expands to 1.SILENT: (or true.SILENT: or whatever) which is meaningless to make.
You can use the option make --silent which will suppress output for all targets. If you want to suppress output for some commands, you can prefix them by #
I like something like this:
$(obj)environment.o: $(src)environment.c
#echo building $#
#$(CC) $(AFLAGS) -Wa, --no-warn \
-DENV_CRC=$(shell $(obj)../tools/envcrc) \
-c -o $# $(src)environment.c
The #echo ... gives a minimal status message, the '#' in front of the $(CC) suppresses standard output (but still allows error messages).
You can use this syntax : #$(CC) $(AFLAGS) -Wa, --no-warn \...

defining a variable in makefile with special characters -- -MF"$(#:%.o=%.d)"

I want to run the next line in a makefile:
g++ -O2 -g -Wall -c -fmessage-length=0 -MMD -MP -MF"$(#:%.o=%.d)" -o "$#" "$<"
I want to define a variable that will contain all the flags:
FLAGS := -O2 -g -Wall -c -fmessage-length=0 -MMD -MP -MF"$(#:%.o=%.d)"
and then use this variable instead of the hardcoded line:
g++ $(FLAGS) -o "$#" "$<"
however the last part of the above line (the quoted part) creates problems.
my question is how can I assign this line to a variable? I tried all kind of escape characters combinations but nothing seems to work.
thanks.
The issue comes from the FLAGS :=. Indeed, using the := operator to set the FLAGS variable instructs make to evaluate the value of the variable only once and now. However, at the time of the definition of FLAGS, variable # is not defined. It will only be defined within the rule that has the g++ command. That's why it results in -MF"".
You should use FLAGS= (no column). Defined with the simple =, the FLAGS variable will only be evaluated when used, i.e. in the g++ command line. At that place, the $# variable will be defined and valid.

Pattern replacement for variable declarations in GNU make

In GNU make, is it possible to use pattern replacement for variable declarations? For example, this is a valid target
obj/%.o: src/%.c
gcc -c src/$*.c -o obj/$*.o
but this doesn't work
BUILD_% = gcc -c src/%.c -o obj/%.o
I see three separate questions here.
First: can % be used and interpreted in recipes? For instance:
gcc -c src/%.c -o obj/%.o
The answer is that it cannot: during rule resolution, % is evaluated in targets and prerequisites, but not in recipes. Instead, you have to use $*, which is roughly but not exactly the same thing.
Second (if I understand your question correctly): can variables used in defining recipes? For instance:
BUILD = gcc -c src/$*.c -o obj/$*.o
obj/%.o: src/%.c
$(BUILD)
Yes, they can.
Third (if this is what you mean to ask at all): can rules be parametrized with variables such that the % placeholder is taken from a variable in which it acts as an argument?
No, not really. You can use a combination of the predefined $(foreach ...), $(call ...), and $(eval ...) functions to specify rules parametrized with values taken from variables, but the values of those variables cannot be supplied by the rule resolution process like the value of %.

Is optimization and generating debug info part of compilation or linkage

I am reading a Makefile from someone else as follows.
LDFLAGS=-lm -ljpeg -lpng
ifeq ($(DEBUG),yes)
OPTIMIZE_FLAG = -ggdb3 -DDEBUG -fno-omit-frame-pointer
else
OPTIMIZE_FLAG = -ggdb3 -O3
endif
CXXFLAGS = -Wall $(OPTIMIZE_FLAG)
all: test
test: test.o source1.o source2.o
$(CXX) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
Makefile.depend: *.h *.cc Makefile
$(CC) -M *.cc > Makefile.depend
clean:
\rm -f test *.o Makefile.depend
-include Makefile.depend
Here are my questions:
Although not explicitly, is $(CXXFLAGS) used by the implicit rule not shown in this Makefile during compilation to generate object files?
I am also wondering why $(CXXFLAGS) appears in the linkage stage? I think it is only for compilation stage? Can I remove $(CXXFLAGS) from "$(CXX) $(CXXFLAGS) -o $# $^ $(LDFLAGS)"? If I am wrong, does it mean g++ also generate debugging info and doing optimization at linkage?
why use -ggdb3 -O3 together for nondebugging purpose? What whould its purpose be? If merely considering to improve speed, then isn't using -O3 only better?
for debugging purpose, how using -ggdb3 -fno-omit-frame-pointer together will do better than -ggdb3 alone? I trying to understand the purpose of -fno-omit-frame-pointer by reading gcc document but still confused.
can I move " -include Makefile.depend" to be just under "$(CC) -M *.cc > Makefile.depend" and above "clean"? Does its position in Makefile matter?
CXXFLAGS is used by the implicit rule. Do make -n -p to see the complete list of variables and rules that Make generates from its internal rule sets and the make file.
-g debugging options are only used at the compile stage. -O options are used at the compile and link stages, potentially. You can use both together. From my gcc man page:
GCC allows you to use -g with -O.
The shortcuts taken by optimized code
may occasionally produce surprising
results:
some variables you declared may not exist at all; flow of control
may briefly move where you did not
expect it; some
statements may not be executed because they compute constant
results or their values were already
at hand; some state-
ments may execute in different places because they were
moved out of loops.
Nevertheless it proves possible to debug optimized output.
This makes it reasonable to use the
optimizer for programs that might have bugs.
-fno-omit-frame-pointer actually reduces the optimization. The optimization can interfere with debugging and the person who wrote this makefile clearly intended to run the debugger on optimized code. If it's unclear to you from the gcc manual how it works, you might want to sit down some Saturday with the Intel or AMD architecture reference manual and learn about function calls and argument passing at the instruction level. (Then again, maybe not. :) )
Position matters in Makefiles. I would leave that include file at the end. To do otherwise risks breaking the include file dependency checking.

Resources