Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building and using a pure llvm toolchain for c++ on linux

Assuming this is possible, could someone tell me, how I have to configure the cmake build to create a "pure" llvm toolchain on ubuntu-16.04 consisting of

  • clang
  • lld
  • libc++
  • libc++abi
  • libunwind (llvm)
  • compiler-rt
  • any other pieces that might be relevant and are "production ready"

The resulting compiler should

  • be as fast as possible (optimizations turned on, no unnecessary asserts or other checks in the compiler binary itself)
  • be installed in a separate, local directory (lets call it <llvm_install>)
  • not have dependencies to the llvm tolchain provided by packet manager
  • use libc++, libc++abi etc by default.
  • support the sanitizers (ubsan, address, memory, thread) (which probably means that I have to compile libc++ a second time)

So far I have cloned

  • llvm from http://llvm.org/git/llvm.git into <llvm_root>
  • clang from http://llvm.org/git/clang.git into <llvm_root>/tools/clang
  • lld from http://llvm.org/git/lld.git into <llvm_root>/tools/lld
  • compiler-rt, libcxx, libcxxabi, libunwind from http://llvm.org/git/<project_name> into <llvm_root>/projects/<project_name>

Then run ccmake in a separate directory - I have tried various settings, but as soon as I try anything more fancy beyond turning optimizations on, I almost always get some sort of build error. Unfortunately, I have yet to find a way to export my changes from ccmake otherwise I'd give you an example with the settings and according error, but I'm more interested in a best practice than a fix to my test configs anyway.

Bonus points: By default, this should build with the default g++ toolchain, but I'd also be interested in a two stage build if that improves the performance of the final toolchain (e.g. by using LTO).

Btw.: The whole Idea came from watching chandler's talk
Pacific++ 2017: Chandler Carruth "LLVM: A Modern, Open C++ Toolchain"

like image 346
MikeMB Avatar asked Nov 15 '17 10:11

MikeMB


1 Answers

My usual procedure is to build a small enough LLVM/Clang so that I have something working with libc++ and libc++abi. I guess you can use the system-provided LLVM, but I haven't tried it. For this step, what you have checked-out is probably enough. A sample script for this:

cmake
-G Ninja \
-DCMAKE_EXPORT_COMPILE_COMMANDS=On \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DBUILD_SHARED_LIBS=On \
-DLLVM_ENABLE_ASSERTIONS=Off \
-DLLVM_TARGETS_TO_BUILD="X86" \
-DLLVM_ENABLE_SPHINX=Off \
-DLLVM_ENABLE_THREADS=On \
-DLIBCXX_ENABLE_EXCEPTIONS=On \
-DLIBCXX_ENABLE_RTTI=On \
-DCMAKE_INSTALL_PREFIX=[path-to-install-dir] \
[path-to-source-dir]

Having the aforementioned clang in your PATH environment variable, you can use the below build script again and adjust based on your needs (sanitizers, etc). Apart from the main documentation page on the subject, poking around the CMakeLists.txt of each respective tool is also illuminating and helps adjust the build process from version to version.

LLVM_TOOLCHAIN_LIB_DIR=$(llvm-config --libdir)
LD_FLAGS=""
LD_FLAGS="${LD_FLAGS} -Wl,-L ${LLVM_TOOLCHAIN_LIB_DIR}"
LD_FLAGS="${LD_FLAGS} -Wl,-rpath-link ${LLVM_TOOLCHAIN_LIB_DIR}"
LD_FLAGS="${LD_FLAGS} -lc++ -lc++abi"

CXX_FLAGS=""
CXX_FLAGS="${CXX_FLAGS} -stdlib=libc++ -pthread"

CC=clang CXX=clang++ \
cmake -G Ninja \
-DCMAKE_EXPORT_COMPILE_COMMANDS=On \
-DBUILD_SHARED_LIBS=On \
-DLLVM_ENABLE_LIBCXX=On \
-DLLVM_ENABLE_LIBCXXABI=On \
-DLLVM_ENABLE_ASSERTIONS=On \
-DLLVM_TARGETS_TO_BUILD="X86" \
-DLLVM_ENABLE_SPHINX=Off \
-DLLVM_ENABLE_THREADS=On \
-DLLVM_INSTALL_UTILS=On \
-DLIBCXX_ENABLE_EXCEPTIONS=On \
-DLIBCXX_ENABLE_RTTI=On \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="${CXX_FLAGS}" \
-DCMAKE_SHARED_LINKER_FLAGS="${LD_FLAGS}" \
-DCMAKE_MODULE_LINKER_FLAGS="${LD_FLAGS}" \
-DCMAKE_EXE_LINKER_FLAGS="${LD_FLAGS}" \
-DCMAKE_POLICY_DEFAULT_CMP0056=NEW \
-DCMAKE_POLICY_DEFAULT_CMP0058=NEW \
-DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \
[path-to-source-dir]

A note on performance: I haven't watched that talk yet, but my motivation behind this 2 step build was to have a toolchain that I can easily relocate between systems since the minimal system dependence that matters is libc.

Lastly, relevant to the above procedure is this older question of mine, which still bugs me. If you have any insight on this, please don't hesitate.

PS: Scripts have been tested with LLVM 3.7 through 3.9 and current trunk 6.0.0.

Update: I've also applied these suggestions, and there is marked improvement when using the gold linker instead of ld. LTO is also a boost.

like image 98
compor Avatar answered Nov 17 '22 10:11

compor