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
好吧,这很长。但是,正如您所看到的,一些标志是重复的。这是第一个命令中的重复:
-O3
重复了4次。
-fno-plt
重复3次。
-fstack-protector-strong
重复3次
-march=x86-64
重复3次。
-mtune=generic
重复3次。
-pipe
重复3次。
除了传递给链接器的 -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
会修复。
所以强调,是的,标志的重复和排序可能很重要。
我在为 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
好吧,这很长。但是,正如您所看到的,一些标志是重复的。这是第一个命令中的重复:
-O3
重复了4次。-fno-plt
重复3次。-fstack-protector-strong
重复3次-march=x86-64
重复3次。-mtune=generic
重复3次。-pipe
重复3次。
除了传递给链接器的 -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
会修复。
所以强调,是的,标志的重复和排序可能很重要。