How to force clang to use some library by default?

2019-02-11 14:58发布

问题:

I build clang by clang against libc++, libc++abi, compiler-rt in the following steps:

  • To download (and update) llvm and sub-projects I use the following script:

    svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
    cd llvm/tools
    svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
    svn co http://llvm.org/svn/llvm-project/clang-tools-extra/trunk clang/tools/extra
    svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb
    svn co http://llvm.org/svn/llvm-project/lld/trunk lld
    svn co http://llvm.org/svn/llvm-project/polly/trunk polly
    cd ../projects/
    svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
    svn co http://llvm.org/svn/llvm-project/libunwind/trunk libunwind
    svn co http://llvm.org/svn/llvm-project/openmp/trunk openmp
    svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk libcxxabi
    svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx
    
  • First of all I build llvm, clang, libunwind against libgcc and libstdc++ using gcc and install them in /usr/local. In all the following steps except the last one I use this fresh clang/clang++.

  • Then I separately build libunwind, both the 32-bit and 64-bit versions (they are essential, as will be further, because asan needs the 32-bit versions of some libraries during the final compilation of the whole project tree) and install it in /usr/local/lib and /usr/local/lib32 correspondingly (also I update LD_LIBRARY_PATH respectively).
  • Build libcxxrt ABI library both 32-bit and 64-bit versions and install them properly.
  • Build libcxx against libcxxrt both 32-bit and 64-bit versions and install them properly.
  • Then build libc++abi against libc++ both 32-bit and 64-bit versions and install them properly.
  • Then build libc++ against libc++abi both 32-bit and 64-bit versions and install them properly over the previous version linked to libcxxrt.
  • After all I build the whole project tree against libc++, libc++abi, libunwind, compiler-rt and install it over old clang in /usr/local.

(I am almost sure that no step is redundant here.)

At the final step I have a problem: I have to add extra parameters to the linker (I add them to CMAKE_EXE_LINKER_FLAGS and CMAKE_SHARED_LINKER_FLAGS) -lunwind and -lc++abi. Moreover, every time I use the resulting clang++ with -stdlib=libc++ and compiler-rt (or, equally, CLANG_DEFAULT_CXX_STDLIB=libc++ and CLANG_DEFAULT_RTLIB=compiler-rt) in my projects I have to do it over and over. It annoying. Say Qt Creator generated project's CMakeLists.txt should be corrected by hand or by cmake-gui.

How to make clang driver to automatically specify these options to ld at runtime? Is there something similar to RPATH mechanism? Or is there some specific CMake variable (specified before llvm building process) to achieve desired behaviour?

Can I use RPATH for my purposes?

Surely I don't want to make some bash-script like wrappers (similar to clang++-libc++) to specify additional parameters. I want the libraries to be hardcoded somewhere in the clang binary itself.

回答1:

There are a couple of workarounds have been suggested. I ended up with the following workaround:

mkdir build
cd build
# backup:
cp -vaf /usr/local/lib/libc++.{a,so.1.0} /usr/local/lib/libc++abi.{a,so.1.0} /usr/local/lib/libunwind.{a,so.1.0} .
clang -shared -fPIC -pthread -o fuse.so -Wl,--whole-archive libc++.a libc++abi.a libunwind.a -Wl,--no-whole-archive -ldl -lm
ar x libc++.a
ar x libc++abi.a
ar x libunwind.a
ar rc fuse.a *.o
sudo chown root:root fuse.*
sudo cp -vaf fuse.so /usr/local/lib/
sudo ln -svf /usr/local/lib/libc++.so.1 /usr/local/lib/fuse.so
sudo cp -vaf fuse.a /usr/local/lib/
sudo mv -vf /usr/local/lib/libc++.a /usr/local/lib/libc++.a.bak
sudo ln -svf /usr/local/lib/libc++.a /usr/local/lib/fuse.a

It merges all the libraries used (libc++, libc++abi and libunwind) into the one single *.a or *.so file. Then libc++.a and libc++.so are replaced with (links to) resulting assemblied files, saving a previous versions for possible backup.

It works perfectly for me.

But this is not the answer. Maybe someday clang will not have such a problem right from the box.