gcc 标志重复和排序重要吗?

Is gcc flags repetition and ordering important?

我在为 python 构建 C 扩展时看到一些 gcc 标志重复出现。当我 运行:

python setup.py build_ext

运行ning 构建命令如下所示:

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

好吧,这很长。但是,正如您所看到的,一些标志是重复的。这是第一个命令中的重复:

除了传递给链接器的 -Wl,... 标志之外,这些标志重复和排序有什么意义吗?

在 GCC 命令行中看到重复的选项并不罕见 由某些工具堆栈(通常是 IDE)生成的,其中 人工输入 "at the top".

None 您发现的重复对 命令行的意思。通常这样的重复只是无害的 冗余,他们可以有一个理性的 动机。向 GCC 命令行增量添加内容的工具可能 希望确保此时启用某个选项,即使它 自上次启用它以来附加的选项可能以某种方式禁用了它。重复 冗余选项可能比检查它是否冗余更便宜。

但重复不一定无害...

如果选项 OPT 出现在命令行中的某个位置:

 ... OPT ...

然后用 2 次或更多次替换出现的一次不会有什么不同。

但是,如果命令行的形式为:

 ... OPT1 ... OPT2 ...

然后在 OPT2 之后的任何地方添加另一个 OPT1 可能会产生一个 区别。同样在 OPT1.

之前的任何位置添加另一个 OPT2

那是因为选项出现的顺序经常出现 差异。

一个选项通常由一个标志和一个组成,例如

 -O3             -> Flag = -O, value = 3
 -I./inc         -> Flag = -I, value = ../inc

一些标志,比如-O可以取一组相互 独有的价值。简称为 mutex flags。当互斥标志重复出现时 反补贴值,命令行中的 last 为准:

 -O1 -O2 -O3 = -O3
 -O3 -O2 -O1 = -O1

其他标志,如-I,可以任意取 非排他性值连续累积,按照它们出现的顺序,形成一个序列 是编译或链接的参数之一。例如

 -I./foo -I./bar

./foo./bar 附加到用户指定的包含目录 编译的搜索顺序。称这些 累积标志 .

其他标志是布尔值,具有启用形式和禁用形式 形式,例如-fstack-protector, -fno-stack-protector。这些可以等同于互斥选项 唯一的可能值 True 和 False。

还有另一种标志,如 -l,接受任意非排他性值 连续 不是 累加,但每个都只是成为标志的值 那时 在命令行中。据我所知,-l 是唯一的此类标志, 这是一种异常类型:-lfoo 并不是真正的 选项 而是 位置参数 旗帜附有解释方法。它说一个文件 libfoo.{so|a}此时要输入链接,其绝对路径 链接器将通过算法发现(参考 -L 选项)。让我们 将此类标志称为 位置标志

对于互斥标志,如果一个选项可以改变命令行的含义 在某处发生的事情稍后会重复发生。例如

 -fno-stack-protector -O1 -O3 -fstack-protector

看起来已经有太多厨师破坏了肉汤,而且 相当于:

 -O3 -fstack-protector

但是如果我们追加一些重复:

 -fno-stack-protector -O1 -O3 -fstack-protector -fno-stack-protector -O1

它等同于:

 -O1 -fno-stack-protector

对于累积标志,更容易设想混淆含义 通过重复一个选项 before 比 after:

 -I./foo -I./bar

意思就是它所说的。而

 -I./bar -I./foo -I./bar

等同于:

 -I./bar -I./foo

但这种混乱在实践中几乎不会发生,因为重复 选项几乎总是由 appending 生成 在增量构建期间重复命令行。

根据定义,位置标志对 order 敏感 以及关于其他选项和位置参数。

的每个排列
 ... -lfoo -lbar main.o ...

产生不同的链接。并且 重复 带有位置标志的选项 也可以轻松有所作为。众所周知,

... -lfoo main.o ... 

很可能会导致链接失败,

    ... -lfoo main.o -lfoo

会修复。

所以强调,是的,标志的重复和排序可能很重要。