Reputation: 4617
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?
Upvotes: 4
Views: 1659
Reputation: 61585
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.
Upvotes: 6