如何在 c++ Autotools 项目中使用不同版本的 g++ 进行编译
Posted
技术标签:
【中文标题】如何在 c++ Autotools 项目中使用不同版本的 g++ 进行编译【英文标题】:How can I compile with different version of g++ in c++ Autotools project 【发布时间】:2018-12-25 09:18:25 【问题描述】:我有一个大的autotools项目,子目录下一部分代码使用g++-4.9编译,其他使用g++8.2。
我的问题是如何用不同版本的g++编译整个项目。
我看到一些相关的问题是更改不同的 g++ 编译器,一般答案是设置环境变量或make
选项。
但是,我的问题是同时使用 g++8.2 和 g++4.9 进行编译。
我希望有一些解决方案可以设置 Makefile.am 像:
noinst_PROGRAMS=foo bar
foo_CXX_COMPILER=/usr/bin/g++-4.9
bar_CXX_COMPILER=/usr/bin/g++-8.2
编辑:
我尝试过的更多细节:
-
子项目中的第三方库在使用
g++-4.9 -std=c++11
编译时会显示很多警告“auto_ptr
is deprecated”,但没有任何错误并且执行良好。
它编译良好,没有错误和g++-4.9 -std=c++98
警告。
当我使用g++-8.2
编译时,它会喊出许多错误“未定义的引用...”,即使我添加了标志-std=c++98.
我猜这是因为g++-8.2
编译器无法识别auto_ptr
的用法!
我更喜欢只使用一种编译器,它可以让问题变得简单!但是,如果情况不能只使用一个,我想知道如何使用不同的两个编译器设置 Makefile.am,或者解决这个编译问题的任何最佳方法!
【问题讨论】:
您需要两个不同的构建目标:一个用于您的程序(库?)和它依赖的文件(目标文件、库等),使用 g++8.2 构建,另一个用于构建g++4.9。如果您需要使用每个编译器进行构建,请设置另一个构建目标,该目标依赖于两个特定于编译器的构建。 你确定不能用 g++8.2 构建所有东西吗?也许通过为您认为需要 v4.9 的目标添加一些额外的选项?这将是一个更具前瞻性的解决方案。 @JohnBollinger : 我的子项目使用的第三方库 (Hazelcast Client c++) 应该根据这个answer 使用 g++-4.9 或更低版本。我尝试使用 g++-8.2 进行编译,它显示了很多错误,例如“未定义对 ... 的引用”。在使用 g++-4.9 时,它运行良好。那个 Hazelcast Client C++ Library 好像是个老库了! 您链接到的 Google 线程是关于 Hazelcast 无法使用太旧、不太新的 C++ 标准库,我在其中没有看到任何关于g++4.9 是极限。如果您自己无法弄清楚,那么提出一个关于使用 g++ 8.2 构建 Hazelcast 的(单独的)问题可能是值得的。仅仅因为您看到很多错误并不一定意味着解决方案很复杂。并且试图在同一个项目中使用不同版本的 C++ 标准库是个坏消息。 @eric_hsu:避免评论你自己的问题。 请edit您的问题以改进它。 提及问题中的所有库,并明确告诉我们它们是用什么 C++ 方言编码的(C++98、C++14、C+ +17, ...) 【参考方案1】:我的问题是如何用不同版本的g++编译整个项目。
这是可能的,但我不建议这样做。 GNU 构建系统对此没有任何支持,但您可以看看 AX_CC_FOR_BUILD 如何实现类似的想法(为构建和主机启用编译器)。
想法#2 是@JohnBollinger 建议的——选择一个编译器并用它构建。 与设置两个编译器相比,您构建的最终用户会更喜欢这一点。这是我会采用的解决方案,因为 GNU 构建系统就是这样工作的。如果由于某种原因不能对旧代码进行现代化改造,可以告诉 g++-8.2 从以前版本的 C++ 编译代码。
想法 #3 基本上是将您的项目拆分为两个 autotools 项目——一个使用旧编译器编译,一个使用新编译器编译。也不是这个想法的真正粉丝。
【讨论】:
【参考方案2】:我有一个大的autotools项目,子目录下一部分代码使用g++-4.9编译,其他使用g++8.2。
我的问题是如何用不同版本的g++编译整个项目。
我不建议这样做。 ABI 约定可能已更改(因此恕我直言,不建议使用不同 ABI 的两个不同 GCC 进行编译)。
实际上,我建议使用相同(最新)的 GCC 构建所有项目,即使用 g++
8.2
如果项目的某些部分使用不同的 C++ 方言,您可以显式地将一些 -std=c++11
或 -std=c++17
选项传递给它们。
所以只需将您的项目配置为使用相同(和最新的)GCC。如果某些 C++ 方言不同,请将特定标志传递给它。请参阅options controlling the C++ dialect 和-std=
option。
最后,您可以考虑修补旧库的源代码,使其与 C++14 兼容(特别是,删除所有出现的 auto_ptr
并明智地将它们替换为 unique_ptr
等...)。在大多数情况下,这样做是值得的(也许旧库的新版本已经存在,即 C++14 或 C++17)
混合使用C++ standard library 的两个不同版本肯定很痛苦,应该避免。如果你坚持尝试,你需要痛苦地理解所有血淋淋的细节(所以我真的建议不要尝试这个)。然后阅读 Drepper 的 How to write shared libraries 论文。
另一种方法是让您的软件使用两个不同的processes(一个用于旧的 C++98 源代码,另一个用于新的 C++14 代码)并使用inter-process communication 工具。这可能是最可靠的解决方案。
出于实际目的,将旧 C++98 和新 C++14 视为两种不同且不兼容的编程语言(C++11确实不同其前身)。
【讨论】:
谢谢!我确定它应该使用标志 -std=c++11。因此,如果我想使用g++-8.2
来编译我的整个大项目,它应该添加一些 Options Controlling C++ Dialect 标志,就像您发布的那样。我只是简单地查看了一下,我应该传递的可能标志是 -fabi-version=n、-fabi-compat-version=n 和 -侘寂=n。但是,当我将 n
的值设置为 2 和 8 时,它在我的测试中不起作用。这是正确的设置方法吗?
我不知道你是否需要设置它。但可能不会。
子项目中在g++4.9中编译良好的第三方库使用已弃用的auto_ptr
。当我通过修改-std=option
或控制方言的选项 使用g++8.2 编译时,它仍然显示很多错误“未定义对...的引用”。我猜这是因为不推荐使用的类型无法在 g++-8.2 中编译!我对吗?如果是这样,我将采用@Idav1s 的第一和第三个建议来调查解决方案。
您可能需要明智地链接(可能是两个不同的 C++ 标准库)
感谢您明智地构建 c++ 项目的建议!在一个项目中遇到两个编译器真的很痛苦。我终于克隆了第三方库的源代码,用我默认的g++
(8.2)自己手动构建。这使我的项目成功构建在一个编译器中!此外,将库版本从 3.10 更新到 3.11。我不确定为什么这种方式解决了这个问题。我猜我链接的原始共享库可能会在g++4.9
中构建,这会在链接时导致g++8.2
中的编译错误。那是对的吗 ?无论如何,它解决了!以上是关于如何在 c++ Autotools 项目中使用不同版本的 g++ 进行编译的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 autotools 与库同时构建 Python 接口