Mas Bagol
Mas Bagol

Reputation: 4617

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:

Beside -Wl,... flags which are passed to linker, does those flags repetition and ordering have any meanings?

Upvotes: 4

Views: 1659

Answers (1)

Mike Kinghan
Mike Kinghan

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

Related Questions