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

时间:2018-10-18 12:43:43

标签: gcc compiler-flags

在为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 个答案:

答案 0 :(得分:2)

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

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

但是重复不一定是无害的...

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

 ... OPT ...

然后用2个或多个替换该事件不会有什么作用。

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

 ... OPT1 ... OPT2 ...

然后在OPT1之后的任何地方添加OPT2可能会导致 区别。同样,在OPT2之前的任何位置添加OPT1

这是因为在其中经常出现选项的 order 差异。

一个选项通常由一个 flag 和一个 value 组成,例如

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

某些标记,例如-O可以采用一组相互之间的任何一个 排他值。简称为这些 mutex标志。当互斥标志反复出现时 抵消值,以命令行中的 last 为准:

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

其他标记(例如-I)可以任意使用 非排它性的值,按照出现的顺序依次累加,形成一个序列 是编译或链接的参数之一。例如

 -I./foo -I./bar

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

其他标志为布尔型,具有启用形式和禁用形式 表格-fstack-protector-fno-stack-protector。这些可以等同于具有 排除可能的值True和False。

还有另一种标志,例如-l,可以接受任意的非排他值 依次 not 累积,但每个只是成为标志的值 此时在命令行中 。据我所知,-l是这种类型的唯一标志, 这是一种异常类型:-lfoo实际上不是 option ,而实际上是 position参数 标志附加了一种解释方法。它说一个文件 此时将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

对于累积标志,更容易设想混淆含义 通过在出现的之前之后的位置重复选项

 -I./foo -I./bar

表示它的意思。而

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

表示与以下内容相同:

 -I./bar -I./foo

但是在实践中几乎不会发生这种混乱,因为重复 选项几乎总是由 append 生成的 在增量构造过程中重复执行命令行。

根据定义,位置标记对 order 都很敏感 以及其他选项和位置参数。

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

产生不同的联系。以及带有位置标志的选项的重复 也可以轻松地有所作为。众所周知,

... -lfoo main.o ... 

可能会导致链接失败,

    ... -lfoo main.o -lfoo

将修复

因此,很重要,是的,标志的重复和排序很重要。