Can Clang可以用GCC编译的.a libs编译代码吗?

时间:2014-01-02 03:33:19

标签: linux gcc clang static-libraries static-linking

我的项目目前正在gcc下进行编译。它使用Boost,ZeroMQ作为静态.a库和一些.so库,如SDL。我想一路铿锵但不是现在。我想知道是否有可能编译使用在gcc下使用clang编译的.a.so库的代码?

3 个答案:

答案 0 :(得分:14)

是的,您通常可以将clang与GCC编译库一起使用(反之亦然,使用gcc与CLANG编译库),因为实际上它不是编译但是linking这是相关的。你可能不走运,并且会感到不愉快。

原则上你可以对用于链接相关库的libstdc++版本有一些依赖关系(如果用C ++编码)。实际上,这通常无关紧要。

在C ++中,name mangling理论上可能是一个问题(可能存在一些极端情况,甚至两个不同版本的g++之间的不兼容性)。同样,在实践中通常不是问题。

所以通常你可以将CLANG(甚至是不同但非常接近的版本)与GCC混合,但你可能会有令人不快的意外。任何C ++编译器(无论是CLANG还是GCC)都应该能够使用相同的编译器和版本来编译和链接整个软件(和所有库)(包括相同的C++ standard library 实施)。这就是为什么升级分发中的编译器需要做很多工作的原因:分发制造商必须确保所有的包都能很好地编译(并且确实会出现意外!)。

请注意libstdc ++的版本很重要。 Clang& GCC社区努力使其ABI兼容编译器升级,但有一些微妙的角落案例。阅读特定和特定C ++标准库实现的文档。在使用GCC 8编译的代码中使用一个好的C ++库二进制文件(用GCC 5编译)时,这些极端情况可以解释神秘的崩溃。该错误不在库中,但ABI演变不相容。

答案 1 :(得分:3)

至少Crypto++ library这不起作用(已验证:-()。因此,对于c ++代码,它不太可能工作,而纯c代码可能链接正常。

编辑:问题开始出现在Mac OS X 10.9 Mavericks和Xcode-5中,它将用于clang的默认C ++库从libstdc ++切换到libc ++。它在Mac OS X 10.8及更早版本中不存在。

解决方案似乎是:如果您需要使用clang编译C ++代码,并将其链接到gcc编译的库,请使用“clang ++ -stdlib = libstdc ++”。链接成功,生成的二进制文件正确运行。

CAVEAT:它似乎没有相反的方式:即使你可以构建一个用“clang ++ -stdlib = libstdc ++”编译的库并用它链接gcc编译的代码,这段代码也会因SEGV而崩溃。到目前为止,我发现链接到clang编译库的唯一方法是使用clang编译代码,而不是gcc。

答案 2 :(得分:0)

关于混合来自不同版本的不同编译器的代码的“令人不快的意外”主题,我确实有一个额外的数据点可以提供帮助。其中,我将Victor Shoup的基于C ++的NTL数字理论库与一小段驱动程序代码链接,该驱动程序代码仅打印出由NTL代码计算出的大阶乘,该数字具有小数表示形式,如果足够大,则可能跨越多行。

我已经在运行OS X 10.11.6的系统上构建并安装了SageMath(及其NTL版本),并且还具有最新的MacPorts安装。在/ usr / bin中,我找到了gcc --version

Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin15.6.0

我的MacPorts gcc给出了

gcc (MacPorts gcc9 9.1.0_2) 9.1.0

现在,SageMath构建系统要求将MacPorts移开,因此我假设SageMath使用Apple的开发工具集构建NTL。 SageMath构建日志中充满了gcc的调用。如果运行makefile的系统版本太旧,则SageMath实际上会从源代码构建gcc。

我的驱动程序代码计算大阶乘并使用NTL类ZZ的方法;最初,我通过链接到自己构建的NTL静态库进行了测试,然后将其更改为链接到SageMath版本,因为我发现它不希望重复库。现在,我进一步了解了此过程中可能出现的陷阱。

旧的makefile调用g ++来生成可执行文件,但是在链接阶段出现以下消息失败:

Undefined symbols for architecture x86_64:
"NTL::operator<<(std::basic_ostream<char, std::char_traits<char> >&, NTL::ZZ const&)",
referenced from:
          prn_factorial(int, NTL::ZZ&)  in print.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status

我不得不考虑这个问题并进行大约15分钟的实验,然后自己决定更改makefile来调用clang ++,而在我当前的路径中,该clang ++会调用MacPorts版本

clang version 7.0.1 (tags/RELEASE_701/final)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /opt/local/libexec/llvm-7.0/bin

这次,makefile成功链接并构建了我的可执行文件。我得出结论,这代表了那些带有“令人不愉快的意外”的极端情况。也许我应该得出结论,使用C ++的细节对我而言并不适合。像SageMath这样的大型软件系统都是经过开发的,因此,爱好者不必真正了解这些细节。