将多个-std开关传递给g ++

时间:2016-11-12 13:20:51

标签: gcc g++ options

假设使用

运行g++是否安全
g++ -std=c++98 -std=c++11 ...

将使用C ++ 11编译?我还没有在documentation中找到明确的确认信息,但我看到-O标记就是这样的。

1 个答案:

答案 0 :(得分:6)

GCC manual没有声明 指定的任何互斥-std=...选项的最后一个生效。第一次出现 或最后一次出现是唯一的选择。有很多 GCC标志从有限集中采用互斥的替代值 - 相互作用 独家,至少模数翻译单位的语言。我们简称为互斥选项。 对于它的记录,最后一个设置生效,这似乎是一个随机的罕见。它是 记录了-O选项,如您所述,也可能是相互排斥的警告选项的一般术语 其他。从未记录多个设置的第一个生效,因为 它永远不会成真。

文档在历史惯例上倾斜 - 具有不完美的一致性 unix-like操作系统中的命令用法。如果命令接受互斥锁选项 然后该选项的最后一次出现生效。如果命令是 - 异常 - 只有在第一次出现选项时才会采取行动,那么这将是一个错误 接受后续发生的命令:它应该给出一个使用错误。

这是习惯和做法。自定义使用工具来编写脚本 尊重它,例如脚本可以调用传递某些默认设置的工具 互斥选项,但允许用户通过脚本参数覆盖该设置, 其值可以简单地附加到默认调用。

如果没有正式的GCC文档,您可能会得到 通过尝试找到任何不是的GCC互斥选项来保证安全 最后一次出现的情况。这是一个刺:

我将编译并链接此程序:

<强>的main.cpp

#include <cstdio>

#if __cplusplus >= 201103L 
static const char * str = "C++11";
#else
static const char * str = "Not C++11";
#endif

int main() 
{
    printf("%s\n%d\n",str,str); // Format `%d` for `str` mismatch
    return 0;
} 

使用命令行:

g++ -std=c++98 -std=c++11 -m32 -m64 -O0 -O1 -g3 -g0 \
-Wformat -Wno-format -o wrong -o right main.cpp

请求相互矛盾的选项对:

  • -std=c++98 -std=c++11:符合C ++ 98。符合C ++ 11。
  • -m32 -m64:生成32位代码。生成64位代码。
  • -O0 -O1:根本不进行优化。优化到1级。
  • -g3 -g0:发出最大调试信息。不发送调试信息。
  • -Wformat -Wno-format。完整性检查printf参数。不要理智地检查它们。
  • -o wrong -o right。输出程序wrong。输出程序right

无需诊断即可成功构建:

$ echo "[$(g++ -std=c++98 -std=c++11 -m32 -m64 -O0 -O1 -g3 -g0 \
-Wformat -Wno-format -o wrong -o right main.cpp 2>&1)]"
[]

它不输出任何程序wrong

$ ./wrong
bash: ./wrong: No such file or directory

输出程序right

$ ./right
C++11
-1713064076

告诉我们它已编译为C++11,而不是C++98

垃圾-1713064076暴露的错误未被诊断出来,因为 -Wno-format,而非-Wformat生效。

它是64位,而不是32位可执行文件:

$ file right
right: ELF 64-bit LSB shared object, x86-64 ...

优化-O1,而不是-O0,因为:

$ "[$(nm -C right | grep str)]"
[]

表示本地符号str不在符号表中。

它不包含调试信息:

echo "[$(readelf --debug-dump right)]"
[]

根据-g0,而不是-g3

由于GCC是开源软件,另一种解决疑虑的方法 关于它对C程序员可用的行为,至少, 是检查相关的源代码,可通过git source-control at获得 https://github.com/gcc-mirror/gcc

您问题的相关源代码位于文件gcc/gcc/c-family/c-opts.c中, 功能,

/* Handle switch SCODE with argument ARG.  VALUE is true, unless no-
   form of an -f or -W option was given.  Returns false if the switch was
   invalid, true if valid.  Use HANDLERS in recursive handle_option calls.  */
bool
c_common_handle_option (size_t scode, const char *arg, int value,
            int kind, location_t loc,
            const struct cl_option_handlers *handlers);

它基本上是scode枚举的选项设置的简单切换梯形图 选项OPT_std_c__11-std=c++11 - 毫无疑问 无论先前生效的设置如何,都会将-std选项设置生效。您可以查看master以外的分支 (gcc-{5|6|7}-branch)得出同样的结论。

找到依赖于其有效性的GCC构建系统脚本并不罕见 通过附加新设置覆盖选项设置。在法律上,这个 通常依靠无证件行为,但有一个更好的 俄罗斯加入北约的机会比GCC不再采取最后的设定 它解析互斥锁选项。