链接到使用GCC5

时间:2015-10-27 12:39:06

标签: c++ c++11 clang abi gcc5

我尝试使用ubuntu 15.10存储库版本的libmuparser(包libmuparser2v5)。用gcc编译工作正常,但不能用clang编译。我深入研究了这个问题,提出了以下最小(非)工作实例和几个问题。

考虑一个带有简单类的库,该类需要string并返回string

testlib.h

#pragma once

#include <string>

struct Test {
    std::string str;

    void set(std::string s);
    std::string get();
};

testlib.cpp

#include "testlib.h"

void Test::set(std::string s) {
    str = s;
}

std::string Test::get() {
    return str;
}

使用gcc 5.2.1编译为带有

的静态库
g++ -Wall -c testlib.cpp -o testlib-gcc.o
ar rcs libtest-gcc.a testlib-gcc.o

现在正在编译应用程序main.cpp

#include <iostream>
#include "testlib.h"

int main()
{
    Test p;
    p.set("Hello!");
    std::cout << p.get() << std::endl;
    return 0;
}

使用clang 3.6.2-1

clang++ main.cpp -o out-clang libtest-gcc.a

导致错误

main.cpp:(.text+0x79): undefined reference to `Test::get()'

现在我发现gcc5有一个名为ABI标签的新功能,可以帮助版本库并防止链接,当它不兼容时。看静态库

$ nm -gC libtest-gcc.a

给出:

testlib-gcc.o:
0000000000000026 T Test::get[abi:cxx11]()
0000000000000000 T Test::set(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)

因此,为cxx11添加了ABI标记get,但set没有添加。当方法返回string时,显然会添加标记。这就是为什么clang声称只是没有找到Test::get()

我想这样做是为了给get一个调用签名,该签名表明需要c ++ 11来链接该函数。对于set,由于类型中的__cxx11,这不是必需的。

问题:

  • 我的猜测是对的,还是可以添加更多内容?
  • 如果是这样,如何解决这个问题?
    • 库编写者可以做什么来使库可以链接到gcc 5.2和clang 3.6编译代码? (源代码更改?
    • 库用户可以使用gng 5.2编译和链接clang 3.6,反之亦然。 (源代码更改或编译标志?
    • 软件包维护者可以做什么来使库可以链接到gcc 5.2和clang 3.6编译代码? (编译标志?
    • 未来版本(哪个版本)的 clang开发者会解决这个问题吗? (默认情况下 ABI兼容性?)但是现在有一个解决方案仍然很好,因为在ubuntu 15.10和衍生产品上很难使用clang。

其他信息:

  • 编译get时定义testlib.cpp的签名。因此共享对象不会有任何区别。也可以使用nm -gC testlib-gcc.o查看符号。
  • 在使用clang编译的库中,get的签名为Test::get()。然后gcc找不到符号Test::get[abi:cxx11](),因此兼容性相互破坏。
  • 对gcc(找到here)使用编译标记-D_GLIBCXX_USE_CXX11_ABI=0是没有解决方案,因为那时集的签名也发生了变化:Test::set(std::string)(但是get很好然后)。
  • 在clang中使用编译标志-stdlib=libc++似乎没有帮助,因为它还报告了对Test::get()的未定义引用(以及更多未定义的引用)。

0 个答案:

没有答案
相关问题