this project builds a complete and standalone llvm suite targeting x86_64 glibc linux hosts and has component and feature parity with traditional gcc + binutils + gdb setups. it requires nothing provided by neither gcc nor binutils, and has no runtime dependencies except for glibc.
- clang
- compiler-rt
- libcxx
- libcxxabi
- libunwind
- lld
- lldb
- openmp
clang{,++}
provided by default uses compiler-rt
and libunwind
instead of
libgcc{_s}
, libc++{,abi}
instead of libstdc++
and ld.lld
instead of
ld.bfd
.
there also symlinks installed to $ROOT/compat/
to act as drop-in replacements
for corresponding gnu utilities to combat hardcoded calls for ld
, gcc
, g++
or cc
, c++
etc. without requiring source modifications.
libc++
(which is linked against libc++abi
statically, which itself is
statically linked against libunwind
), libunwind
, and libomp
(openmp) are
provided in static library forms to remove the existence of the toolchain as
runtime dependency.
libLLVM
, libclang*
, liblld*
and liblldb*
are left as shared libraries
to allow for projects such as rust to be built with it or for module support to
be possible.
simply run ./build.sh
in the root directory of this repo. it is assumed that
you have the build requirements, if not the case, peep into the Dockerfile
.
this simply installs build-time dependencies and runs build.sh
inside whatever
the latest debian version is.
docker compose run --build=true \
bootstrap-llvm \
/bin/bash -c './build.sh' --build
however you may have chosen to proceed, you should have a tarball in out/
in
the root of this repo.
because RUNPATH
for all binaries are set $ORIGIN/../lib
as per llvm cmake
defaults, the path where the toolchain gets placed at does not cause any type of
breakage so setting LD_LIBRARY_PATH
is not necessary for using components of
the resulting toolchain.
however, setting LIBRARY_PATH
to $ROOT/lib
and -I$ROOT/include -L$ROOT/lib
to {C,LD}FLAGS
during build-time, and setting LD_LIBRARY_PATH
to $ROOT/lib
during runtime in cases where you link against the shared libraries provided is
necessary.
certain cmake projects might force a specific CMAKE_C{,XX}_COMPILER_TARGET
and
this may result in cmake exiting during c{,++} compiler sanity checks. this is
due to this project having compiled the clang runtime for the
x86_64-mss-linux-gnu
target triple:
# default behavior
$ clang -print-libgcc-file-name
/release/lib/clang/18/lib/x86_64-mss-linux-gnu/libclang_rt.builtins.a
# ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^
# when --target is specified
$ clang --target=x86_64-unknown-linux-gnu -print-libgcc-file-name
/release/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64.a
# ^^^^^ ^^^^^^^^^^^^^^^
simply setting -DCMAKE_C_COMPILER_TARGET
and -DCMAKE_CXX_COMPILER_TARGET
to
x86_64-mss-linux-gnu
will fix this.
$ find . -type f -exec file {} ';' | grep ELF\ 64-bit \
| awk '{print $1}' | sed 's/:$//g' | xargs objdump -p \
| grep NEEDED | sort | uniq
NEEDED ld-linux-x86-64.so.2 # libc
NEEDED libclang-cpp.so.18.1 # self
NEEDED libc.so.6 # libc
NEEDED liblldb.so.18.1 # self
NEEDED libLLVM.so.18.1 # self
NEEDED libm.so.6 # libc
LLVM_PATH="/path/to/release"
PATH="${LLVM_PATH}/bin:${LLVM_PATH}/compat:${PATH}"
LD_LIBRARY_PATH="${LLVM_PATH}/lib:${LD_LIBRARY_PATH}"
LIBRARY_PATH="${LLVM_PATH}/lib:${LIBRARY_PATH}"
export PATH LD_LIBRARY_PATH LIBRARY_PATH
CC="${LLVM_PATH}/bin/clang"
CXX="${LLVM_PATH}/bin/clang++"
LD="${LLVM_PATH}/bin/ld.lld"
AR="${LLVM_PATH}/bin/llvm-ar"
AS="${LLVM_PATH}/bin/clang"
NM="${LLVM_PATH}/bin/llvm-nm"
STRIP="${LLVM_PATH}/bin/llvm-strip"
RANLIB="${LLVM_PATH}/bin/llvm-ranlib"
OBJCOPY="${LLVM_PATH}/bin/llvm-objcopy"
OBJDUMP="${LLVM_PATH}/bin/llvm-objdump"
OBJSIZE="${LLVM_PATH}/bin/llvm-size"
READELF="${LLVM_PATH}/bin/llvm-readelf"
ADDR2LINE="${LLVM_PATH}/bin/llvm-addr2line"
export CC CXX LD AR AS NM STRIP RANLIB OBJCOPY OBJDUMP OBJSIZE READELF ADDR2LINE
CPPFLAGS="-DMYDEF=MYVAL"
CFLAGS="${CPPFLAGS} -O2 -pipe -I${LLVM_PATH}/include -L${LLVM_PATH}/lib"
CXXFLAGS="${CFLAGS}"
LDFLAGS="${CFLAGS} -Wl,--as-needed,--sort-common,-z,relro,-z,now"
export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS