求助:ccls的编译问题,链接不通过

我编译ccls时遇到了困难,不知道是我的环境哪里出了问题。

环境: Ubuntu 16.04,clang-llvm 7.0.1

按照宋教授的Wiki中的指令运行,运用的就是Prebuilt的16.04的Binaries。

$ cmake -H. -BRelease -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/path/to/clang+llvm-xxx
$ cmake --build Release

然后我先碰见了第一个错,找不到<optional>头文件。经过一番Google和试验,我强行在CMakeLists.txt里加了这么一句

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")

好,编译没有问题了,全部通过,结果出现了链接错误,在我一波瞎试后以失败而告终 :sweat_smile:。求助各位如何解决。感谢!!

PS:

部分Error Msg如下,完整的有一万多行

......

/data/terrytsao/software/clang+llvm-7.0.1-x86_64-linux-gnu-ubuntu-16.04/lib/libLLVMSupport.a(TargetRegistry.cpp.o): In function `llvm::TargetRegistry::lookupTarget(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, llvm::Triple&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)':
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0x38): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::compare(char const*) const'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0x7d): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::reserve(unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0xa8): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0xb9): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0xde): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0x192): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::swap(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0x1f8): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::reserve(unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0x223): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0x232): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0x257): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0x2ab): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::swap(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_6TripleERS6_+0x2e8): undefined reference to `std::__throw_length_error(char const*)'
/data/terrytsao/software/clang+llvm-7.0.1-x86_64-linux-gnu-ubuntu-16.04/lib/libLLVMSupport.a(TargetRegistry.cpp.o): In function `llvm::TargetRegistry::lookupTarget(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)':
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS6_+0xf4): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned long&, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS6_+0x152): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS6_+0x1af): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace(unsigned long, unsigned long, char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS6_+0x20c): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS6_+0x280): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS6_+0x2e8): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS6_+0x347): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::swap(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
TargetRegistry.cpp:(.text._ZN4llvm14TargetRegistry12lookupTargetERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS6_+0x3b1): undefined reference to `std::__throw_length_error(char const*)'
/data/terrytsao/software/clang+llvm-7.0.1-x86_64-linux-gnu-ubuntu-16.04/lib/libLLVMSupport.a(Threading.cpp.o): In function `llvm::heavyweight_hardware_concurrency()':
Threading.cpp:(.text._ZN4llvm32heavyweight_hardware_concurrencyEv+0xf): undefined reference to `std::thread::hardware_concurrency()'
/data/terrytsao/software/clang+llvm-7.0.1-x86_64-linux-gnu-ubuntu-16.04/lib/libLLVMSupport.a(Threading.cpp.o): In function `llvm::hardware_concurrency()':
Threading.cpp:(.text._ZN4llvm20hardware_concurrencyEv+0x34): undefined reference to `std::thread::hardware_concurrency()'
/data/terrytsao/software/clang+llvm-7.0.1-x86_64-linux-gnu-ubuntu-16.04/lib/libLLVMSupport.a(Errno.cpp.o): In function `llvm::sys::StrError[abi:cxx11]()':
Errno.cpp:(.text._ZN4llvm3sys8StrErrorB5cxx11Ev+0x5c): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace(unsigned long, unsigned long, char const*, unsigned long)'
/data/terrytsao/software/clang+llvm-7.0.1-x86_64-linux-gnu-ubuntu-16.04/lib/libLLVMSupport.a(Errno.cpp.o): In function `llvm::sys::StrError[abi:cxx11](int)':
Errno.cpp:(.text._ZN4llvm3sys8StrErrorB5cxx11Ei+0x5a): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace(unsigned long, unsigned long, char const*, unsigned long)'
clang-7: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [ccls] Error 1
make[1]: *** [CMakeFiles/ccls.dir/all] Error 2
make: *** [all] Error 2

只弄过windows

我终于解决了,原因是没有装libstdc++-7,导致链接始终不过。

问题似乎和宋教授在Wiki里的这一段话有关

but likely won’t work on Linux due to conflict of libstdc++ (linked by clang+llvm libraries) and libc++

我的理解是这里说了Ubuntu版的prebuilt的clang+llvm库链接了libstdc++-7,所以这里不能缺了这个库,不知道理解是否正确,艾特一下大神 @MaskRay 确认一下 :sweat_smile:

你要用ldd看一下你的ccls,看看他依赖了哪些包,我自己编译的clang7,他的libc++不依赖libstdc++。如果离不开libstdc++,就直接连接他好了

set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -stdlib=libc++”)

-stdlib=libc++同時是compiler option和linker option。用作

  • compiler option: 不添加libstdc++ include directory。執行clang::driver::toolchains::Linux::addLibCxxIncludePaths$ResourceDir/include/c++ /usr/local/include/c++等路徑獲取libc++ include directory
  • linker option: 鏈接時添加-lc++。你沒有用這個導致鏈接錯誤。

我的理解是这里说了Ubuntu版的prebuilt的clang+llvm库链接了 libstdc++-7

你缺了libstdc++-7-dev

% readelf -d build/clang+llvm-7.0.1-x86_64-linux-gnu-ubuntu-18.04/lib/libclang.so.7 | grep 'NEEDED.*libstdc'
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
% dpkg -S /usr/lib/gcc/x86_64-linux-gnu/7/libstdc++.so 
libstdc++-7-dev:amd64: /usr/lib/gcc/x86_64-linux-gnu/7/libstdc++.so
% readelf -d /usr/lib/gcc/x86_64-linux-gnu/7/libstdc++.so | grep SONAME
 0x000000000000000e (SONAME)             Library soname: [libstdc++.so.6]
% dpkg -S /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
libstdc++6:amd64: /usr/lib/x86_64-linux-gnu/libstdc++.so.6

鏈接時選取的libstdc++.so,其SONAME爲libstdc++.so.6,運行時指向libstdc++.so.6.* (resolve symlink後)

but likely won’t work on Linux due to conflict of libstdc++ (linked by clang+llvm libraries) and libc++

如果llvm/clang libraries用libstdc++編譯,那麼編譯它的header files也得用libstdc++。 假如ccls編譯時-stdlib=c++,那麼因爲ccls includes llvm/clang headers,這些headers也會用libc++。

libraries提供的libstdc++符號集和依賴的libc++符號集不同=>鏈接錯誤。

其實一個程序同時鏈接libstdc++和libc++是可行的。倘若你同時鏈接libstdc++和libc++到ccls,而clang/llvm是libstdc++,可以解決鏈接錯誤,但會導致更嚴重的問題:ccls裏創建的libstdc++的std::string傳遞到clang/llvm會被解釋成libstdc++ std::string=>segfault

3 个赞

我用的是centos 7,系统gcc是4.9.2,不得已只能自己编译了llvm-7.0.1和gcc-7.4.0,连接libc++运行时直接崩溃,只能使用gcc-7.4.0,加-DCMAKE_CXX_FLAGS="-D_GLIBCXX_USE_CXX11_ABI=0 -D__STDC_FORMAT_MACROS -Wl,-rpath /usr/local/gcc/7.4.0/lib64" 完美解决。主要是新gcc abi改了,得强制用回老格式。

其实gcc-4.9.2支持c++14,没有看过ccls源码,如果能去掉c++17的依赖就简单了。

其实我也尝试过-lc++,前面忘了说了,但是链接还是不通过,请问这是什么原因?

我这边也遇到同样的错误,但是我的机器没有sudo权限,有其他方法可以解决这个问题吗

你可以像他一样自己编clang,用libc++不依赖libstdc++