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

Posted

技术标签:

【中文标题】gcc 标志重复和排序重要吗?【英文标题】:Is gcc flags repetition and ordering important? 【发布时间】:2018-10-18 12:43:42 【问题描述】:

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

python setup.py build_ext

正在运行的构建命令如下所示:

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,...标志之外,这些标志的重复和排序是否有任何意义?

【问题讨论】:

【参考方案1】:

在 GCC 命令行中看到重复选项并不罕见 由某些工具堆栈(通常是 IDE)生成的,带有 人工输入“在顶部”。

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

但重复不一定无害……

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

 ... OPT ...

然后用 2 个或更多替换一个匹配项不会有任何影响。

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

 ... OPT1 ... OPT2 ...

然后在OPT2 之后的任何位置添加另一个OPT1 可能会产生 不同之处。同样,在 OPT1 之前的任何位置添加另一个 OPT2

这是因为选项经常出现的顺序 区别。

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

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

一些标志,如-O 可以取一组相互之间的任何一个 独家价值观。简称为这些互斥标志。当互斥标志重复出现时 反补贴值,命令行中的 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

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

根据定义,位置标志对 order 敏感,两者都在它们之间 以及与其他选项和位置参数有关。的每一个排列

 ... -lfoo -lbar main.o ...

产生不同的链接。以及带有位置标志的选项重复 也可以很容易地有所作为。众所周知,

... -lfoo main.o ... 

很可能会导致链接失败,

    ... -lfoo main.o -lfoo

会解决的。

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

【讨论】:

以上是关于gcc 标志重复和排序重要吗?的主要内容,如果未能解决你的问题,请参考以下文章

glUniformBlockBinding 和 glBindBufferBase 之间的排序重要吗?

如何使用 jQuery 在 css 中设置重要标志? [复制]

GCC 中 -faligned-new 的值

GCC -g vs -g3 GDB 标志:有啥区别?

GCC优化内存访问[重复]

GCC 优化标志