【问题标题】:Why does the order of clang compiler flags affect the resulting binary size?为什么 clang 编译器标志的顺序会影响生成的二进制大小?
【发布时间】:2015-12-20 03:57:13
【问题描述】:

替代标题:为什么我的 dylib 在 Xcode vs Makefile 编译时包含额外的导出符号?

我的公司使用 clang 在 Mac 上构建了一个 c++ 动态库 (dylib),我们最近将我们手工制作的 Makefile 移植到了 CMake 构建系统,现在正在使用生成的 Xcode 项目。在确保所有编译器/链接器标志和环境变量在两个系统之间完全匹配后,我们注意到由 CMake/Xcode 创建的 dylib 稍大一些。仔细检查表明它包含一些额外的导出符号(来自从未引用的模板函数,因此不应该被实例化 - 特定模板在源文件中具有它们的定义和特化,因为我们经常使用显式实例化,尽管在这种情况下它们没有显式实例化)。检查一些目标文件的反汇编也显示出轻微的指令差异。使库在大小和符号上完全匹配的唯一方法是完全匹配编译器标志的顺序。这似乎表明编译器标志之间存在一些依赖于顺序的交互,这似乎是编译器错误或至少记录不充分的行为。

对于这个特定问题,这些是编译器调用:

clang++ -fvisibility=hidden -fvisibility-ms-compat -c foo.cpp -o foo.o

clang++ -fvisibility-ms-compat -fvisibility=hidden -c foo.cpp -o foo.o

这是链接器调用:

clang++ -dynamiclib -o libfoo.dylib foo.o

显示导出的符号:

nm -g libfoo.dylib

显示了差异。我提交了这个LLVM Bug

是否存在编译器标志排序很重要的有效情况?

【问题讨论】:

  • 另请注意,如果您尝试精确匹配二进制大小,如果您包含调试符号 (-g),则执行编译的目录很重要,因为文件路径将包含在对象中文件。

标签: c++ xcode macos clang


【解决方案1】:

微软的编译器和几乎所有其他的编译器在目标文件中的符号可见性传统上都有非常不同的模型。前者长期使用 C 和 C++ 语言扩展来控制编译器的符号发射,默认不导出符号。

-fvisibility=hidden-fvisibility-ms-compat 似乎可能是互斥的,并且编译器会尊重在其命令行上看到的最后一个。

平心而论,除了将其添加到 clang 的提交之外,几乎没有关于 -fvisibility-ms-compat 的文档。

【讨论】:

  • 我找到了一些关于 -fvisibility-ms-compat here 的官方文档,其中指出: -fvisibility=hidden 在 -fvisibility-ms-compat 也在命令行上时无效。这确实表明标志是互斥的,但是,我仍然不明白为什么标志的顺序会产生任何影响。编译器根据它们的相对位置覆盖标志是典型的做法吗?是否有任何其他预期此类行为的示例?
猜你喜欢
  • 1970-01-01
  • 2013-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多