我知道原则上这可能是未定义的行为,但为了处理大型项目,这是我关于GCC的问题:
假设我使用完全相同的编译器安装,使用gcc -std=c++98
编译一个转换单元,使用-std=c++11
编译另一个转换单元。是否有任何保证可以链接两个目标文件并获得定义良好的程序?
据我所知,由于不同的宏,潜在的问题只能来自库标题的不同视图,反过来这些问题最多只能添加新的成员函数,但从来不是成员对象,标准库类。
这会以某种方式使用不同的语言方言选项编译更大项目的不同部分是否可以接受?
更新:我应该添加一个正交的问题:如何使用两个不同的版本的GCC(比如4.3和4.6),但相同方言选项(-std=c++98
)?列表in this GCC documentation似乎表明该库在4.2.2和4.6之间的两个方向兼容。
答案 0 :(得分:10)
先验,没有。最安全的解决方案是假设所有的编译器选项都是相同的,除非编译器专门记录该选项不影响二进制兼容性。 (在大多数编译器中都非常缺乏的文档。)在实践中,由于缺少文档,似乎可以肯定的是,控制警告的选项(g ++中的-W...
)不会影响二进制兼容性,以及哪些选项影响代码生成(语言级别等)可能:g ++通常保持不同优化级别之间的兼容性,而VC ++则不然。
另一个真正的问题是在命令行中定义预处理程序符号。同样,最安全的选择是所有定义都是相同的,但同样,一些常识是有序的:人们很难指望标准库是用你的项目中使用的预处理器符号编译的(像{{ 1}},说)。另一方面,请注意MYPROG_CONFIG_FILE_LOCATION
和_GLIBCXX_DEBUG
的预处理器定义将影响二进制兼容性(尽管g ++确保您获得一个与它们一起使用的库版本,如果您一致地使用它们)。
关于你的问题:由于标准版本,我不希望对二进制兼容性有太大影响,但是如果选择影响某些预定义的预处理器符号,那么我不会感到惊讶这种方式会破坏库中的二进制兼容性,就好像你用_GLIBCXX_DEBUG_PEDANTIC
编译了一些模块,有些没有。它可能会奏效,但我不会指望它。
答案 1 :(得分:3)
我知道原则上这可能是未定义的行为,
不是。
假设我使用完全相同的编译器安装,使用
gcc -std=c++98
编译一个转换单元,使用-std=c++11
编译另一个转换单元。是否有任何保证可以链接两个目标文件并获得定义良好的程序?
是的,这是支持和有效的(有一些例外,比如在一个对象中启用调试模式而不是另一个对象,或者在一个而不是另一个中使用明确的ABI更改选项,如-fshort-enums
,但是应该是显而易见的,因为即使你对两个对象都使用相同的-std
选项,它也不会起作用。)
据我所知,由于宏的不同,潜在的问题只能来自库头的不同视图,而这些问题反过来最多会将新的成员函数添加到标准库类中,但绝不会添加成员对象
右。
这会以某种方式使用不同的语言方言选项编译更大项目的不同部分是否可以接受?
对于海湾合作委员会,是的,绝对。作为证据,没关系,请考虑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
库。
答案 2 :(得分:0)
语言ABI是相同的,但STL ABI是不同的。见https://gcc.gnu.org/wiki/Cxx11AbiCompatibility
所以不建议混合使用-std = c ++ 98 -std = c ++ 11编译的库。在跨图像边界传递数据时可能会崩溃。
(如果您只调用extern“C”函数并仅传递POD,则它可能有效。)