Search engines and reading the manuals are failing me. I'm not sure if there's a way to have E.G. gcc or clang output the final 'configuration' result of parsed command line arguments to check myself (nor what keywords might be matches for that in the manuals).
NOT -I includes (don't see a negative for keywords :( )
When running gcc (or) clang, does the Last specified version of an option or the First specified win?
E.G. gcc -O3 -Os -O1 ... -- Would gcc build the result with -O3 or -O1 ?
My guess is that the last / most recent parameter would win, but I'd really prefer knowledge of where in the documentation the behavior is specified and thus made part of the usage contract rather than an undefined and undocumented behavior that happens to work whenever it's tested.
This behavior would differ from the well documented "Include path management" behavior, where (as in most western writing) matches are scanned from 'left to right' (first to last in the specified parameters). However given overriding Includes it also logically makes sense that the first specified version of a singular flag type might win with later redundant specifications ignored.
When running gcc (or) clang, does the Last specified version of an option or the First specified win?
It is not the case that all options, even excluding -I
options, that
can assume multiple values assume mutually exclusive values, so which ones wins does not
necessarily arise. In an answer to a related question I classified options as mutex, cumulative
or positional (although this classification is not endorsed by GCC or Clang documentation
and is empirically based). You may find that answer helpful.
GCC/Clang documentation does not provide an overall procedure for determining how the effect of each option is related to that of others before or after it. The answers vary depending on the nature of the option and you must turn to the documentation pertaining to a class of options.
For example:
In concluding the documention of the -O?
options controlling optimisation level
you can read:
If you use multiple -O options, with or without level numbers, the last such option is the one that is effective.
For any pair of mutually exclusive options of equal generality you can rely on it that the compiler will either diagnose the conflict or take the last one with no diagnostic. You may have to find out experimentally whether you get a diagnostic (e.g. -DX -DX=Y
) or not
(-fPIC -fno-PIC
).
And equal generality is a complication. For example, in concluding the documention of the -Wwarning
options to request or suppress Warnings
you can read:
You can request many specific warnings with options beginning with ‘-W’, for example -Wunused-variable to request warnings on declarations of variables that are never used. Each of these specific warning options also has a negative form beginning with ‘-Wno-’ to turn off warnings; for example, -Wno-unused-variable. This manual lists only one of the two forms, whichever is not the default...
The combined effect of positive and negative forms is that more specific options have priority over less specific ones, independently of their position in the command line. For options of the same specificity, the last one takes effect.
My emphasis.
I'm not sure if there's a way to have E.G. gcc or clang output the final 'configuration' result of parsed command line arguments to check myself.
Yes, you can find out the final operative options consumed by the compiler using
the option -frecord-gcc-switches
. This
option emits in the object file a string section called .GCC.command.line
that contains
the residual commandline options. For example:
$ cat main.c
int main(void)
{
return 0;
}
$ gcc -c main.c -O0 -O3 -fPIC -fno-PIC -frecord-gcc-switches
Then:
$ objdump -s -j .GCC.command.line main.o
main.o: file format elf64-x86-64
Contents of section .GCC.command.line:
0000 474e5520 43313720 31332e33 2e30202d GNU C17 13.3.0 -
0010 6d74756e 653d6765 6e657269 63202d6d mtune=generic -m
0020 61726368 3d783836 2d363420 2d4f3320 arch=x86-64 -O3
0030 2d666e6f 2d504943 202d6661 73796e63 -fno-PIC -fasync
0040 68726f6e 6f75732d 756e7769 6e642d74 hronous-unwind-t
0050 61626c65 73202d66 73746163 6b2d7072 ables -fstack-pr
0060 6f746563 746f722d 7374726f 6e67202d otector-strong -
0070 66737461 636b2d63 6c617368 2d70726f fstack-clash-pro
0080 74656374 696f6e20 2d666366 2d70726f tection -fcf-pro
0090 74656374 696f6e00 tection.
or more legibly:
$ strings main.o
GNU C17 13.3.0 -mtune=generic -march=x86-64 -O3 -fno-PIC -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection
...
shows you the operative options. Here you will see boilerplate options that you did not explicitly pass:
-mtune=generic -march=x86-64 -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection
in addition to ones that you did pass, but if you discount the boilerplate options then the ones you are left with:
-O3 -fno-PIC
are the ones that remained from:
-O0 -O3 -fPIC -fno-PIC
after the compiler had "picked the winners". Note the -frecord-gcc-switches
is not itself
recorded. This option is accepted by Clang as well as GCC.