【问题标题】:Can different GCC dialects be linked together?可以将不同的 GCC 方言联系在一起吗?
【发布时间】:2012-05-29 20:00:48
【问题描述】:

我知道原则上这可能是未定义的行为,但为了处理大型项目,这是我关于 GCC 的问题:

假设我用gcc -std=c++98 编译一个事务单元,用-std=c++11 编译另一个事务单元,使用完全相同的编译器安装。是否有任何保证可以链接两个目标文件并获得定义明确的程序?

据我所知,由于宏的不同,潜在的问题只能来自库头的不同视图,而那些反过来最多添加新的成员函数,但绝不是成员对象,到标准库类。

这是否会让使用不同语言方言选项编译大型项目的不同部分变得可以接受?

更新:我应该添加一个正交问题:如果使用两个 不同 版本的 GCC(比如 4.3 和 4.6),但 相同 em> 方言选项 (-std=c++98)?清单in this GCC documentation 似乎表明该库在 4.2.2 和 4.6 之间双向兼容。

【问题讨论】:

    标签: c++ gcc linker undefined-behavior dialect


    【解决方案1】:

    先验的,不。最安全的解决方案是假设所有编译器选项都是相同的,除非编译器专门记录该选项不会影响二进制兼容性。 (大多数编译器都非常缺乏文档。)在实践中,在缺乏文档的情况下,控制警告的选项(g++ 中的-W...)似乎不会影响二进制兼容性,而影响代码的选项似乎是安全的。生成(语言级别等)可能:g++ 通常保持跨不同优化级别的兼容性,而 VC++ 则没有。

    另一个真正的问题是在命令行中定义预处理器符号。同样,最安全的选择是所有定义都是相同的,但同样,一些常识是有序的:很难指望标准库已经用项目中使用的预处理器符号编译(例如@987654322 @, 说)。另一方面,请注意 _GLIBCXX_DEBUG_GLIBCXX_DEBUG_PEDANTIC 的预处理器定义会影响二进制兼容性(尽管 g++ 确保如果您始终使用它们,您将获得与它们一起使用的库版本)。

    关于您的问题:由于标准版本,我不希望对二进制兼容性产生太大影响,但是如果选择会影响某些预定义的预处理器符号,我不会感到惊讶,在这种方式会破坏库中的二进制兼容性,就像您使用_GLIBCXX_DEBUG 编译了一些模块,而没有编译了一些模块一样。它可能会起作用,但我不会指望它。

    【讨论】:

    • “很难指望标准库已经用项目中使用的预处理器符号编译”——即使是这样,暂时假设宏 MYPROG_CONFIG_FILE_LOCATION 是在memset.c 中使用,那么定义到memset.c 的含义与它在您的程序中的含义完全无关。因此,如果编译 memset.c 使用/不使用 MYPROG_CONFIG_FILE_LOCATION 会对二进制兼容性产生影响,那么它将独立于您的程序是否碰巧也使用 MYPROG_CONFIG_FILE_LOCATION
    • @SteveJessop 是的。即使是这样,它也应该对你透明。实际上,命名空间中的所有预处理器符号(即不以下划线开头,也不包含两个相邻的下划线)应该是安全的。实现命名空间中的预处理器符号(如 _GLIBCXX_DEBUG)不会。
    【解决方案2】:

    我知道原则上这可能是未定义的行为,

    不是。

    假设我用gcc -std=c++98 编译一个事务单元,用-std=c++11 编译另一个事务单元,使用完全相同的编译器安装。是否有任何保证可以链接两个目标文件并获得定义明确的程序?

    是的,这是受支持且有效的(有例外,例如在一个对象中启用调试模式而不是在另一个对象中,或者在一个对象中而不是另一个对象中使用显式 ABI 更改选项,例如 -fshort-enums,但这应该是很明显,因为即使您对两个对象使用相同的 -std 选项,这也不起作用)。

    据我所知,由于宏的不同,潜在的问题只能来自库头的不同视图,而这些反过来最多只会向标准库类添加新的成员函数,而不是成员对象.

    没错。

    这是否会让使用不同语言方言选项编译大型项目的不同部分变得可以接受?

    对于 GCC,是的,绝对是。作为证明没问题,考虑libstdc++.so 本身包含一些用-std=c++98 构建的对象和一些用-std=c++14 构建的对象。

    更新:我应该添加一个正交问题:使用两个不同版本的 GCC(比如 4.3 和 4.6),但使用相同的方言选项(-std=c++98)怎么样?此 GCC 文档中的列表似乎表明该库在 4.2.2 和 4.6 之间的两个方向上都兼容。

    不是双向,您需要使用 GCC 4.6(或更高版本)中的 libstdc++.so,因为使用该版本编译的对象可能依赖于新版本中引入的符号,而旧版本中不存在libstdc++.so图书馆。

    一些相关信息https://stackoverflow.com/a/49119902/981959

    【讨论】:

      【解决方案3】:

      Language ABI 相同,但 STL ABI 不同。见https://gcc.gnu.org/wiki/Cxx11AbiCompatibility

      所以不建议混合使用 -std=c++98 -std=c++11 编译的库。跨图像边界传递数据时可能会发生崩溃。

      (如果你只调用 extern "C" 函数并且只传递 POD,它可能会起作用)。

      另见相关:Mixing different C++ standards with GCC

      【讨论】:

      • 那个 wiki 页面似乎不是最新的 :-(
      猜你喜欢
      • 2016-10-08
      • 1970-01-01
      • 1970-01-01
      • 2015-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-22
      • 1970-01-01
      相关资源
      最近更新 更多