LLVM - MaskRay/Config GitHub Wiki

Build modes

Common build modes which are worth testing for fiddling with build systems.

  • default
  • -DBUILD_SHARED_LIBS=on
  • -DLLVM_LINK_LLVM_DYLIB=on
  • (asan) -DLLVM_USE_SANITIZER=Address -DLLVM_ENABLE_RUNTIMES=

Configuration

git config blame.ignoreRevsFile .git-blame-ignore-revs
git config feature.manyFiles true
# lldb docs use sphinx-automodapi
pip3 install --user myst-parser recommonmark sphinx sphinx-automodapi
# Pretty printing std::string
sudo apt-get install libstdc++6-dbgsym

Recommended minimal configuration

curl -s https://raw.githubusercontent.com/chromium/chromium/main/tools/clang/scripts/update.py | python3 - --output-dir=$HOME/Stable
cmake -GNinja -Sllvm -Bout/release -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=$HOME/Stable/bin/clang++ -DCMAKE_C_COMPILER=$HOME/Stable/bin/clang -DLLVM_ENABLE_PROJECTS='clang;lld;compiler-rt' -DLLVM_TARGETS_TO_BUILD=host -DCMAKE_CXX_ARCHIVE_CREATE="$HOME/Stable/bin/llvm-ar qc --thin <TARGET> <OBJECTS>" -DCMAKE_CXX_ARCHIVE_FINISH=: -DCLANG_ENABLE_ARCMT=off -DCLANG_ENABLE_STATIC_ANALYZER=off
ninja -C out/release clang asan hwasan lsan msan tsan ubsan compiler-rt-headers

My configure-llvm:

#!/bin/zsh
dry_run=
PROJECTS=(-DLLVM_ENABLE_PROJECTS='bolt;clang;clang-tools-extra;flang;lldb;lld;compiler-rt;mlir;polly;libc;cross-project-tests' -DLLVM_ENABLE_RUNTIMES='openmp;libcxx;libcxxabi;libunwind')
SLIM=(-DCLANG_ENABLE_ARCMT=off -DCLANG_ENABLE_STATIC_ANALYZER=off -DCLANG_PLUGIN_SUPPORT=off)

while (($#)); do
  case $1 in
    --full) SLIM=() ;;
    --light) PROJECTS=(-DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;lld;compiler-rt') ;;
    --dry-run) dry_run=1 ;;
    -*) echo "unknown option $1" >&2; exit ;;
    *) break ;;
  esac
  shift
done

LLVM=(-GNinja "${PROJECTS[@]}" "${SLIM[@]}" -DCMAKE_CXX_COMPILER=$HOME/Stable/bin/clang++ -DCMAKE_C_COMPILER=$HOME/Stable/bin/clang -DCMAKE_CXX_ARCHIVE_CREATE="$HOME/Stable/bin/llvm-ar qc --thin <TARGET> <OBJECTS>" -DCMAKE_CXX_ARCHIVE_FINISH=:
  -DLLVM_OPTIMIZED_TABLEGEN=On -DLLVM_APPEND_VC_REV=OFF -DLLVM_ENABLE_LLD=On -DLLVM_ENABLE_UNWIND_TABLES=off -DPython3_EXECUTABLE=/usr/bin/python3
  -DLIBOMPTARGET_BUILD_DEVICERTL_BCLIB=off -DLIBOMPTARGET_BUILD_AMDGPU_PLUGIN=off -DLIBOMPTARGET_BUILD_CUDA_PLUGIN=off -DCMAKE_BUILD_WITH_INSTALL_RPATH=on)
[[ $(uname -a) =~ 'x86_64 GNU' ]] && LLVM=(${LLVM[@]} -DCMAKE_EXE_LINKER_FLAGS='-no-pie' -DCMAKE_SHARED_LINKER_FLAGS='-Wl,-z,pack-relative-relocs')
for i in "${LLVM[@]}"; do
  (($LLVM[(Ie)$i])) && LLVMFULL+=("$i")
done
LLVMFULL+=(-DCLANG_ENABLE_ARCMT=on -DCLANG_ENABLE_STATIC_ANALYZER=on)

linux=
[[ -f /etc/lsb_release ]] && linux=1

cmake() {
  if [[ -n $dry_run ]]; then
    echo cmake "$@"
  else
    command cmake "$@"
  fi
}

# Build with system gcc
if [[ $1 == stable ]]; then
  cmake -GNinja -Sllvm -Bout/stable -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=host -DLLVM_ENABLE_PROJECTS='clang;lld;compiler-rt' ${linux:+-DLLVM_USE_LINKER=gold} -DLLVM_APPEND_VC_REV=OFF ${SLIM}
  [[ -n $dry_run ]] || ninja -C out/stable clang lld msan

# Build with stable clang/lld
elif [[ $1 == preset ]]; then
  cmake -Sllvm -B/tmp/Rel -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/tmp/opt/Rel ${LLVMFULL} -DLLVM_BUILD_EXAMPLES=on -DLLVM_ENABLE_ASSERTIONS=on -DLLVM_ENABLE_{CURL,HTTPLIB,SPHINX}=ON -DLLVM_BINUTILS_INCDIR=$HOME/Dev/binutils-gdb/include -DLLVM_OPTIMIZED_TABLEGEN=Off -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD='ARC;AVR;CSKY;DirectX;LoongArch;M68k;SPIRV;Xtensa' -DLIBCXX_ABI_VERSION=2
  #cmake -Sllvm -B/tmp/Debug -DBUILD_SHARED_LIBS=On -DCMAKE_BUILD_TYPE=Debug ${LLVM} -DCMAKE_CXX_FLAGS_DEBUG='-g -fno-limit-debug-info' -DCMAKE_{EXE,SHARED}_LINKER_FLAGS=-Wl,--gdb-index -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DCOMPILER_RT_DEBUG=On -DLLVM_USE_SPLIT_DWARF=On -DLLVM_BINUTILS_INCDIR=$HOME/Dev/binutils-gdb/include -DLLVM_OPTIMIZE_SANITIZED_BUILDS=OFF -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD='ARC;AVR;LoongArch;M68k;Xtensa'
  cmake -Sllvm -B/tmp/Debug -DBUILD_SHARED_LIBS=On -DCMAKE_BUILD_TYPE=Debug ${LLVM} -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DCOMPILER_RT_DEBUG=On -DLLVM_USE_SPLIT_DWARF=On -DLLVM_BINUTILS_INCDIR=$HOME/Dev/binutils-gdb/include -DLLVM_OPTIMIZE_SANITIZED_BUILDS=OFF -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD='ARC;AVR;LoongArch;M68k;Xtensa'
elif [[ $1 == release ]]; then
  cmake -Sllvm -Bout/release -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=off ${LLVM} -DLLVM_TARGETS_TO_BUILD=host -DLLVM_ENABLE_PROJECTS='clang;lld' -DLLVM_OPTIMIZED_TABLEGEN=Off -DLLVM_ENABLE_PIC=off -DCMAKE_EXE_LINKER_FLAGS=$HOME/Dev/mimalloc/out/release/libmimalloc.a -DCMAKE_CXX_STANDARD=20
elif [[ $1 == laptop ]]; then
  cmake -Sllvm -B$HOME/llvm/out/debug -DBUILD_SHARED_LIBS=On -DCMAKE_BUILD_TYPE=Debug ${LLVM} -DCMAKE_CXX_COMPILER=$HOME/Stable/bin/clang++ -DCMAKE_C_COMPILER=$HOME/Stable/bin/clang -DCMAKE_CXX_ARCHIVE_CREATE="$HOME/Stable/bin/llvm-ar qc --thin <TARGET> <OBJECTS>" -DCMAKE_CXX_ARCHIVE_FINISH=: -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DCOMPILER_RT_DEBUG=On -DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;lld' -DLLVM_TARGETS_TO_BUILD='AArch64;X86;RISCV' -DLLVM_PARALLEL_LINK_JOBS=2 -DLLVM_USE_SPLIT_DWARF=On -DLLVM_OPTIMIZE_SANITIZED_BUILDS=OFF
elif [[ $1 == static-debug ]]; then
  cmake -Sllvm -B/tmp/StaticDebug -DCMAKE_BUILD_TYPE=Debug ${LLVM} -DCMAKE_CXX_FLAGS_DEBUG='-g -fno-limit-debug-info' -DCMAKE_EXE_LINKER_FLAGS=-Wl,--gdb-index -DCMAKE_SHARED_LINKER_FLAGS='-no-pie -Wl,--gdb-index' -DCOMPILER_RT_DEBUG=On -DLLVM_USE_SPLIT_DWARF=On -DLLVM_BINUTILS_INCDIR=$HOME/Dev/binutils-gdb/include "${@:2}"

elif [[ $1 == asan ]]; then
  cmake -Sllvm -Bout/asan -DCMAKE_BUILD_TYPE=RelWithDebInfo ${LLVM} -DCMAKE_CXX_FLAGS_DEBUG='-g1' -DLLVM_USE_SANITIZER=Address -DLLVM_OPTIMIZE_SANITIZED_BUILDS=Off -DLLVM_ENABLE_PROJECTS='clang;lld;clang-tools-extra'
elif [[ $1 == tsan ]]; then
  cmake -Sllvm -B/tmp/out/tsan -DCMAKE_BUILD_TYPE=RelWithDebInfo ${LLVM} -DCMAKE_CXX_FLAGS_DEBUG='-g -fno-limit-debug-info' -DLLVM_USE_SANITIZER=Thread -DLLVM_ENABLE_PROJECTS='clang;lld'
elif [[ $1 == ubsan ]]; then
  cmake -Sllvm -B/tmp/out/ubsan -DCMAKE_BUILD_TYPE=RelWithDebInfo ${LLVM} -DCMAKE_CXX_FLAGS_DEBUG='-g -fno-limit-debug-info' -DLLVM_USE_SANITIZER=Undefined -DLLVM_ENABLE_PROJECTS='clang;lld'

elif [[ $1 == custom* ]]; then
  rm -fr /tmp/out/$1
  cmake -Sllvm -B/tmp/out/$1 -DCMAKE_BUILD_TYPE=Release ${LLVM} "${@:2}"

# Build with a stage-1 clang/lld
elif [[ $1 == s2-debug ]]; then
  LLVM+=(-DCMAKE_CXX_COMPILER=/tmp/Rel/bin/clang++ -DCMAKE_C_COMPILER=/tmp/Rel/bin/clang -DLLVM_OPTIMIZED_TABLEGEN=On -DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;lld;compiler-rt')
  cmake -Sllvm -B/tmp/out/s2 -DCMAKE_BUILD_TYPE=Debug ${LLVM} -DCMAKE_CXX_FLAGS='-g -stdlib=libc++' -DCMAKE_{EXE,SHARED}_LINKER_FLAGS=-stdlib=libc++ -DLLVM_ENABLE_ASSERTIONS=on -DLLVM_OPTIMIZE_SANITIZED_BUILDS=Off "${@:2}"
elif [[ $1 == s2-release ]]; then
  LLVM+=(-DCMAKE_CXX_COMPILER=/tmp/Rel/bin/clang++ -DCMAKE_C_COMPILER=/tmp/Rel/bin/clang -DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;lld;compiler-rt')
  cmake -Sllvm -B/tmp/out/s2-release -DCMAKE_BUILD_TYPE=Release ${LLVM} -DLLVM_ENABLE_ASSERTIONS=on
  #cmake -Sllvm -B/tmp/out/s2-release -DCMAKE_BUILD_TYPE=Release ${LLVM} -DCMAKE_CXX_FLAGS='-stdlib=libc++' -DCMAKE_{EXE,SHARED}_LINKER_FLAGS=-stdlib=libc++ -DLLVM_ENABLE_ASSERTIONS=on
elif [[ $1 == s2-asan* ]]; then
  # ninja clang lld asan compiler-rt-headers
  cmake -Sllvm -B/tmp/out/$1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ${LLVM} -DCMAKE_CXX_COMPILER=/tmp/Rel/bin/clang++ -DCMAKE_C_COMPILER=/tmp/Rel/bin/clang -DLLVM_USE_SANITIZER=Address -DLLVM_OPTIMIZE_SANITIZED_BUILDS=Off -DLLVM_ENABLE_PROJECTS='clang;lld;clang-tools-extra;mlir'
elif [[ $1 == s2-ubsan* ]]; then
  # ninja clang lld ubsan compiler-rt-headers
  cmake -Sllvm -B/tmp/out/$1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ${LLVM} -DCMAKE_CXX_COMPILER=/tmp/Rel/bin/clang++ -DCMAKE_C_COMPILER=/tmp/Rel/bin/clang -DLLVM_USE_SANITIZER=Undefined -DLLVM_OPTIMIZE_SANITIZED_BUILDS=Off -DLLVM_ENABLE_PROJECTS='clang;lld;clang-tools-extra'
elif [[ $1 == s2-custom* ]]; then
  rm -fr /tmp/out/$1
  cmake -Sllvm -B/tmp/out/$1 -DCMAKE_BUILD_TYPE=Release ${LLVM} -DCMAKE_CXX_COMPILER=/tmp/Rel/bin/clang++ -DCMAKE_C_COMPILER=/tmp/Rel/bin/clang "${@:2}"
fi
# Configure /tmp/Rel and /tmp/Debug
configure-llvm preset

Benchmark

configure-llvm custom2 -DLLVM_TARGETS_TO_BUILD=host -DCMAKE_INSTALL_PREFIX=/tmp/opt/custom2 -DCMAKE_EXE_LINKER_FLAGS=~/Dev/mimalloc/out/release/libmimalloc.a -DLLVM_ENABLE_PIC=off -DCMAKE_CXX_FLAGS=-fno-asynchronous-unwind-tables

Copy ccls-cache built from a powerful machine to an underpowered machine.

from=remote
cd ~/llvm

# Make sure timestamps of source files match those of remote's
rsync -tr --existing -f '+ /llvm' -f '+ /clang' -f '+ /clang-tools-extra' -f '+ /lld' -f '+ /lldb' -f '+ /compiler-rt' -f '+ /libcxx' -f '+ /libcxxabi' -f '+ /libunwind' -f '+ /libc' -f '- /*' -f '+ */' -f '+ *.cpp' -f '+ *.h' -f '+ *.def' -f '+ *.inc' -f '- *' ${from}:llvm/ ./

# Make sure generated source files match those of remote's
rsync -a -f '+ */' -f '+ *.def' -f '+ *.inc' -f '+ *.h' -f '+ compile_commands.json' -f '- *' ${from}:llvm/Debug/ Debug/

# Copy ccls cache
mkdir -p .ccls-cache
rsync -a ${from}:llvm/.ccls-cache/@home@ray@llvm/ .ccls-cache/@home@ray@llvm/

MemorySanitizer

Use either of -DLLVM_USE_SANITIZER={Memory,MemoryWithOrigins}. For symbolization, use -g1.

ninja -C ~/llvm/out/stable llvm-ar clang lld msan compiler-rt-headers

LLVM_COMMON=(-GNinja -DCMAKE_CXX_COMPILER=$HOME/llvm/out/stable/bin/clang++ -DCMAKE_C_COMPILER=$HOME/llvm/out/stable/bin/clang -DCMAKE_CXX_ARCHIVE_CREATE="$HOME/llvm/out/stable/bin/llvm-ar qcS --thin <TARGET> <OBJECTS>" -DCMAKE_CXX_ARCHIVE_FINISH=: -DLLVM_APPEND_VC_REV=OFF -DLLVM_ENABLE_LLD=On -DLLVM_TARGETS_TO_BUILD=host -DLLVM_NATIVE_TOOL_DIR=/tmp/Rel/bin -DCLANG_ENABLE_ARCMT=off -DCLANG_ENABLE_STATIC_ANALYZER=off)

libcxx_out=$HOME/llvm/out/msan-libcxx
cmake -Sruntimes -B$libcxx_out $LLVM_COMMON -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RUNTIMES='libcxx;libcxxabi' -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=on -DLLVM_USE_SANITIZER=Memory
ninja -C $libcxx_out cxx cxxabi

sanitizer_ldflags="-Wl,--rpath=$libcxx_out/lib/x86_64-unknown-linux-gnu -L$libcxx_out/lib/x86_64-unknown-linux-gnu -lc++abi"
sanitizer_cflags="-nostdinc++ -isystem$libcxx_out/include/x86_64-unknown-linux-gnu/c++/v1 -isystem$libcxx_out/include/c++/v1"
# See http://llvm.org/bugs/show_bug.cgi?id=19071, http://www.cmake.org/Bug/view.php?id=15264
sanitizer_cflags="$sanitizer_cflags $sanitizer_ldflags -fsanitize=memory -w"
cmake -Hllvm -B/tmp/out/msan ${LLVM_COMMON} -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS='clang;lld' -DCMAKE_C_FLAGS=$sanitizer_cflags -DCMAKE_CXX_FLAGS=$sanitizer_cflags -DCMAKE_EXE_LINKER_FLAGS=$sanitizer_ldflags -DCMAKE_SHARED_LINKER_FLAGS=$sanitizer_ldflags -DLLVM_ENABLE_LIBCXX=On -DLLVM_USE_SPLIT_DWARF=On -DLLVM_USE_SANITIZER=Memory
  • -DBUILD_SHARED_LIBS for building libLLVM*.so libclang*.so instead of libLLVM*.a libclang*.a
  • -DLLVM_ENABLE_LLD for faster linking
  • -DLLVM_USE_SPLIT_DWARF faster linking for Debug RelWithDebInfo. Don't use it for Release.
  • -DLLVM_PARALLEL_LINK_JOBS=1 if memory is small
  • -Wl,--gdb-index for speeding up gdb
  • -DCMAKE_CXX_FLAGS=--stdlib=libc++ -DCMAKE_{EXE,SHARED}_LINKER_FLAGS=--stdlib=libc++: Build clang with libc++
  • -DCMAKE_CXX_ARCHIVE_CREATE="$HOME/Stable/bin/llvm-ar qc --thin <TARGET> <OBJECTS>" -DCMAKE_CXX_ARCHIVE_FINISH=: uses thin archives, which make the output directory much smaller. However, this is not suitable for ninja install (used by downstream projects like Halide) and some compiler-rt -fuse-ld=bfd tests

Cross compilation

TODO:

try

-DLLVM_RUNTIME_TARGETS='default;riscv64-unknown-linux-gnu
-DRUNTIMES_riscv64-unknown-linux-gnu_LLVM_ENABLE_RUNTIMES='compiler-rt'

LLVM_ENABLE_PROJECTS

The following instructions uses LLVM_ENABLE_PROJECTS with -DCMAKE_CROSSCOMPILING=on -DLLVM_DEFAULT_TARGET_TRIPLE=... -DLLVM_TARGET_ARCH=... to cross compile for the specified target. Clang is built, so the process is very slow.

-m32 cross toolchain

configure-llvm custom-x86 -DCMAKE_{C,CXX}_FLAGS=-m32 -DCMAKE_{EXE,SHARED}_LINKER_FLAGS=-m32 -DLLVM_ENABLE_PROJECTS='clang;lld'

musl

-fuse-ld=lld in CFLAGS as a workaround for cross compilation ignores CMAKE_SHARED_LINKER_FLAGS

MUSL=$HOME/Dev/musl-cross-make
cmake -GNinja -Sllvm -B/tmp/out/musl -DCMAKE_BUILD_TYPE=Debug -DLLVM_USE_SPLIT_DWARF=on -DCMAKE_C_COMPILER=~/Stable/bin/clang -DCMAKE_CXX_COMPILER=~/Stable/bin/clang++ -DCMAKE_{C,CXX}_FLAGS="--target=x86_64-linux-musl --sysroot=$MUSL/output/x86_64-linux-musl --gcc-install-dir=$MUSL/output/lib/gcc/x86_64-linux-musl/9.4.0 -fuse-ld=lld -w" -DCMAKE_{EXE,SHARED}_LINKER_FLAGS="-Wl,--dynamic-linker=$MUSL/output/x86_64-linux-musl/lib/libc.so -Wl,-rpath=$MUSL/output/x86_64-linux-musl/lib" -DLLVM_NATIVE_TOOL_DIR=/tmp/Rel/bin -DLLVM_HOST_TRIPLE=x86_64-linux-musl -DLLVM_TARGETS_TO_BUILD=host -DLLVM_ENABLE_PROJECTS='clang;lld'

(Since 16.0.0, use -DLLVM_NATIVE_TOOL_DIR=/tmp/Rel/bin instead of -DLLVM_TABLEGEN=/tmp/Rel/bin/llvm-tblgen -DCLANG_TABLEGEN=/tmp/Rel/bin/clang-tblgen.)

aarch64-linux-gnueabihf cross toolchain, compiled with clang using GCC files

cmake -GNinja -Sllvm -B/tmp/out/a64-0 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/tmp/Rel/bin/clang -DCMAKE_CXX_COMPILER=/tmp/Rel/bin/clang++ -DCMAKE_{C,CXX}_FLAGS='--target=aarch64-linux-gnu' -DLLVM_NATIVE_TOOL_DIR=/tmp/Rel/bin -DLLVM_HOST_TRIPLE=aarch64-linux-gnu -DLLVM_TARGETS_TO_BUILD=AArch64

arm-linux-gnueabihf cross toolchain

cmake -GNinja -Hllvm -B/tmp/out/arm -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/usr/bin/arm-linux-gnueabihf-g++-9 -DCMAKE_C_COMPILER=/usr/bin/arm-linux-gnueabihf-gcc-9 -DCMAKE_CROSSCOMPILING=on -DCMAKE_INSTALL_PREFIX=/tmp/opt/arm -DLLVM_TARGETS_TO_BUILD=ARM -DLLVM_DEFAULT_TARGET_TRIPLE=arm-linux-gnueabihf -DLLVM_TARGET_ARCH=ARM -DLLVM_NATIVE_TOOL_DIR=/tmp/Rel/bin -DLLVM_ENABLE_PROJECTS='clang;libcxx;libcxxabi;compiler-rt'

mips32el-unknown-linux-gnu cross toolchain

cmake -GNinja -Sllvm -B/tmp/out/mips32 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/usr/bin/mipsel-linux-gnu-g++ -DCMAKE_C_COMPILER=/usr/bin/mipsel-linux-gnu-gcc -DCMAKE_CROSSCOMPILING=on -DCMAKE_INSTALL_PREFIX=/tmp/opt/mips -DLLVM_TARGETS_TO_BUILD=Mips -DLLVM_DEFAULT_TARGET_TRIPLE=mipsel-unknown-linux-gnu -DLLVM_TARGET_ARCH=Mips -DLLVM_NATIVE_TOOL_DIR=/tmp/Rel/bin -DLLVM_ENABLE_PROJECTS='clang;compiler-rt'

mips64-unknown-linux-gnuabi64 cross toolchain

cmake -GNinja -Sllvm -B/tmp/out/mips64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/usr/bin/mips64-linux-gnuabi64-g++ -DCMAKE_C_COMPILER=/usr/bin/mips64-linux-gnuabi64-gcc -DCMAKE_CROSSCOMPILING=on -DCMAKE_INSTALL_PREFIX=/tmp/opt/mips64 -DLLVM_TARGETS_TO_BUILD=Mips -DLLVM_DEFAULT_TARGET_TRIPLE=mips64-unknown-linux-gnuabi64 -DLLVM_TARGET_ARCH=Mips -DLLVM_NATIVE_TOOL_DIR=/tmp/Rel/bin -DLLVM_ENABLE_PROJECTS='clang;compiler-rt'

mips64el-unknown-linux-gnuabi64 cross toolchain

cmake -GNinja -Sllvm -B/tmp/out/mips64el -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/usr/bin/mips64el-linux-gnuabi64-g++ -DCMAKE_C_COMPILER=/usr/bin/mips64el-linux-gnuabi64-gcc -DCMAKE_CROSSCOMPILING=on -DCMAKE_INSTALL_PREFIX=/tmp/opt/mips64el -DLLVM_TARGETS_TO_BUILD=Mips -DLLVM_DEFAULT_TARGET_TRIPLE=mips64el-unknown-linux-gnuabi64 -DLLVM_TARGET_ARCH=Mips -DLLVM_NATIVE_TOOL_DIR=/tmp/Rel/bin -DLLVM_ENABLE_PROJECTS='clang;compiler-rt'

# How to use runtimes/? Failed attempt:
#cmake -GNinja -Sruntimes -B/tmp/out/mips64el -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/usr/bin/mips64el-linux-gnuabi64-g++ -DCMAKE_C_COMPILER=/usr/bin/mips64el-linux-gnuabi64-gcc -DCMAKE_CROSSCOMPILING=on -DCMAKE_INSTALL_PREFIX=/tmp/opt/mips64el -DLLVM_ENABLE_RUNTIMES=compiler-rt -DLLVM_TARGETS_TO_BUILD=Sparc -D{LLVM_BUILTIN_TARGETS,LLVM_RUNTIME_TARGETS}=mips64el-unknown-linux-gnuabi64 -DLLVM_DEFAULT_TARGET_TRIPLE=mips64el-unknown-linux-gnuabi64
PATH=/tmp/Rel/bin:$PATH cmake -GNinja -Sruntimes -B/tmp/out/mips64el -DCMAKE_BUILD_TYPE=Release -DCMAKE_CROSSCOMPILING=on -DCMAKE_INSTALL_PREFIX=/tmp/opt/mips64el -DLLVM_ENABLE_RUNTIMES=compiler-rt -DLLVM_TARGETS_TO_BUILD=Sparc -D{LLVM_BUILTIN_TARGETS,LLVM_RUNTIME_TARGETS}=mips64el-unknown-linux-gnuabi64 -DLLVM_DEFAULT_TARGET_TRIPLE=mips64el-unknown-linux-gnuabi64

riscv64-unknown-linux-gnu cross toolchain

cmake -GNinja -Sllvm -B/tmp/out/rv64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/usr/bin/riscv64-linux-gnu-g++ -DCMAKE_C_COMPILER=/usr/bin/riscv64-linux-gnu-gcc -DCMAKE_CROSSCOMPILING=on -DCMAKE_INSTALL_PREFIX=/tmp/opt/rv64 -DLLVM_TARGETS_TO_BUILD=RISCV -DLLVM_DEFAULT_TARGET_TRIPLE=riscv64-unknown-linux-gnu -DLLVM_TARGET_ARCH=riscv64 -DLLVM_NATIVE_TOOL_DIR=/tmp/Rel/bin -DLLVM_ENABLE_PROJECTS='clang;compiler-rt'

sparc64-unknown-linux-gnu cross toolchain

cmake -GNinja -Sllvm -B/tmp/out/sparc64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/usr/bin/sparc64-linux-gnu-g++ -DCMAKE_C_COMPILER=/usr/bin/sparc64-linux-gnu-gcc -DCMAKE_CROSSCOMPILING=on -DCMAKE_INSTALL_PREFIX=/tmp/opt/sparc64 -DLLVM_TARGETS_TO_BUILD=Sparc -DLLVM_DEFAULT_TARGET_TRIPLE=sparc64-unknown-linux-gnu -DLLVM_TARGET_ARCH=Sparc -DLLVM_NATIVE_TOOL_DIR=/tmp/Rel/bin -DLLVM_ENABLE_PROJECTS='clang;compiler-rt'

Default build

Toot the CMake invocation at <monorepo>/runtimes. See https://libcxx.llvm.org/BuildingLibcxx.html#the-default-build

cmake -GNinja -Sruntimes -B/tmp/out/riscv64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CROSSCOMPILING=on -DCMAKE_CXX_COMPILER=/tmp/Rel/bin/clang++ -DCMAKE_C_COMPILER=/tmp/Rel/bin/clang -DCMAKE_{ASM,C,CXX}_COMPILER_TARGET=riscv64-unknown-linux-gnu -DCMAKE_INSTALL_PREFIX=/tmp/opt/riscv64 -DLLVM_ENABLE_RUNTIMES='libcxx;libcxxabi;libunwind;compiler-rt' -D{LLVM_BUILTIN_TARGETS,LLVM_RUNTIME_TARGETS}=riscv64-unknown-linux-gnu -DLLVM_DEFAULT_TARGET_TRIPLE=riscv64-unknown-linux-gnu
ln -sf /tmp/out/riscv64/lib /tmp/Debug/lib/riscv64-unknown-linux-gnu
install -D /tmp/out/riscv64/compiler-rt/lib/linux/libclang_rt.builtins-riscv64.a /tmp/Debug/lib/clang/17/lib/riscv64-unknown-linux-gnu/libclang_rt.builtins.a

/tmp/Debug/bin/clang --target=riscv64-unknown-linux-gnu -g -I ~/llvm/libunwind/include a.c -no-pie --unwindlib=libunwind --rtlib=compiler-rt -ldl -Wl,-E,-rpath,/tmp/out/riscv64/lib -o a

Standalone compiler-rt

Build compiler-rt mips64el (standalone) with prebuilt llvm-config/clang/lld (apt install qemu-user-static g++-mips64el-linux-gnuabi64):

ninja -C /tmp/Rel clang lld llvm-config
# -fPIC compiled files may have .eh_frame referencing DW.ref.__gxx_personality using the encoding DW_EH_PE_absptr.
# GNU ld works around this by converting it to DW_EH_PE_sdata4|DW_EH_PE_pcrel. lld doesn't support this conversion.
cmake -GNinja -Scompiler-rt -B/tmp/out/rt-mips64el -DCMAKE_CROSSCOMPILING=on -DCMAKE_C_COMPILER=/tmp/Rel/bin/clang -DCMAKE_CXX_COMPILER=/tmp/Rel/bin/clang++ -DCMAKE_{ASM,C,CXX}_COMPILER_TARGET=mips64el-unknown-linux-gnuabi64 -DCMAKE_{C,CXX}_FLAGS='-fPIC -D_GNU_SOURCE' -DLLVM_CMAKE_DIR=/tmp/Rel -DLLVM_APPEND_VC_REV=OFF -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=on -DCOMPILER_RT_DEFAULT_TARGET_ONLY=on -DCOMPILER_RT_EMULATOR='qemu-mips64el-static -L /usr/mips64el-linux-gnuabi64' -DCOMPILER_RT_INCLUDE_TESTS=on -DCOMPILER_RT_TEST_COMPILER_CFLAGS=--target=mips64el-unknown-linux-gnuabi64

ninja -C /tmp/out/rt-mips64el
ln -s /tmp/out/rt-mips64el/lib/mips64el-unknown-linux-gnuabi64 -t /tmp/Rel/lib/clang/16/lib
cmake -GNinja -Scompiler-rt -B/tmp/out/rt-aarch64 -DCMAKE_CROSSCOMPILING=on -DCMAKE_C_COMPILER=/tmp/Rel/bin/clang -DCMAKE_CXX_COMPILER=/tmp/Rel/bin/clang++ -DCMAKE_{ASM,C,CXX}_COMPILER_TARGET=aarch64-unknown-linux-gnu -DCMAKE_{C,CXX}_FLAGS='-fPIC -D_GNU_SOURCE' -DCMAKE_{EXE,SHARED}_LINKER_FLAGS=-fuse-ld=lld -DLLVM_CMAKE_DIR=/tmp/Rel -DLLVM_APPEND_VC_REV=OFF -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=on -DCOMPILER_RT_DEFAULT_TARGET_ONLY=on -DCOMPILER_RT_EMULATOR='qemu-aarch64-static -L /usr/aarch64-linux-gnu' -DCOMPILER_RT_HAS_LLD=on -DCOMPILER_RT_TEST_USE_LLD=on -DCOMPILER_RT_INCLUDE_TESTS=on -DCOMPILER_RT_TEST_COMPILER_CFLAGS=--target=aarch64-unknown-linux-gnu

ninja -C /tmp/out/rt-aarch64
ln -s /tmp/out/rt-aarch64/lib/aarch64-unknown-linux-gnu -t /tmp/Rel/lib/clang/16/lib

Don't run check-asan. It is a resource hog and likely doesn't work under qemu.

Unsupported build systems

Bazel

https://github.com/llvm/llvm-www/blob/main/proposals/LP0002-BazelBuildConfiguration.md

cd utils/bazel
bazel-5.0.0 build --config=generic_clang @llvm-project//clang

gn

llvm/utils/gn/get.py
llvm/utils/gn/gn.py gen /tmp/out/gn

llvm/utils/gn/gn.py format llvm/utils/gn/secondary/llvm/tools/*/BUILD.gn

Testing tips

clang/lib/Driver

clang/test/Driver tests are sensitive to CMAKE_DEFAULT_* CMake options. It's a good idea to test both the default and CMAKE_DEFAULT_* set to llvm-project components.

ninja -C /tmp/Rel check-clang-driver

# Default --rtlib=compiler-rt --unwindlib=libunwind --stdlib=libc++
configure-llvm custom -DCLANG_DEFAULT_RTLIB=compiler-rt -DCLANG_DEFAULT_UNWINDLIB=libunwind -DCLANG_DEFAULT_CXX_STDLIB=libc++ -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=on
ninja -C /tmp/out/custom check-clang-driver

# Runtime build
configure-llvm custom -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=on -DLLVM_RUNTIME_TARGETS=default -DLLVM_ENABLE_RUNTIMES='compiler-rt;libcxx;libcxxabi;libunwind' -DLLVM_BUILTIN_TARGETS=default -DLLVM_ENABLE_PROJECTS='clang;lld'

When testing -cc1 command lines, we test -cc1 but not clang{{.*}}: https://github.com/llvm/llvm-project/commit/980679981fbc311bc07f8cd23e3739fd56c22d2a

lld

The testing is very rigid. In particular, all new diagnostics should be tested.

  • ninja check-lld: test all ports. Only relevant when you modify lldCommon.
  • ninja check-lld-elf: test the ELF port.
export LLVM_COMPILER_PATH=~/llvm/Release/bin
cmake -GNinja -H. -BGLLVM -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gclang -DCMAKE_CXX_COMPILER=gclang++ -DCMAKE_C_FLAGS='-Xclang -disable-llvm-passes' -DCMAKE_CXX_FLAGS='-Xclang -disable-llvm-passes'

Build most targets skipping tests

for i in llvm clang clang-tools flang lld lldb bolt mlir; do LIT_OPTS='--filter=xxx --allow-empty-runs' ninja -C /tmp/Rel check-$i; done

Limit resources

systemd-run --user --scope -p CPUQuota=1550% -p MemoryMax=90000M -p MemoryHigh=80000M ninja check-llvm

Land a patch

My ~/bin/llvm-push:

#!/bin/sh
branch=$(git branch --show-current)
if [[ $branch == wip* ]]; then
  echo wip, dont push
  exit
fi

git pull --rebase origin main && git commit --amend --date=now --no-edit && git push origin HEAD:main && git fetch origin main:main && git switch main || exit 1
[[ $branch != main ]] && git branch -d $branch

My ~/bin/spr-push:

#!/bin/zsh
branch=$(git branch --show-current)
git pull --rebase origin main && git commit --amend --date=now --no-edit && spr land && git fetch origin main:main && git switch main || exit 1
[[ $branch != main ]] && git branch -D $branch

How to reproduce build bots

Chromium

https://chromium.googlesource.com/chromium/src/+/master/docs/linux/build_instructions.md

https://source.chromium.org/chromium/chromium/src/+/HEAD:build/config/compiler/BUILD.gn

  • Make sure that .gclient includes target_os = [..., "android"]. If not, run gclient runhooks.
  • cd ~/chromium/src; PATH=~/projects/depot_tools:$PATH gclient sync
  • Run tools/clang/scripts/build.py --llvm-force-head-revision --with-android=True --without-fuchsia to get third_party/llvm
  • Apply local patch and run tools/clang/scripts/build.py --skip-checkout --without-fuchsia
  • There are several build directories. The main one is at third_party/llvm-build/Release+Asserts. android-aarch64 is at third_party/llvm-build/Release+Asserts/android-aarch64.

For Windows, target_os = "win".

Sanitizers

For issues which don't require a bootstrapped compiler, just set -DLLVM_USE_SANITIZER=.

MemrorySanitizer is the trickest because it requires an instrumented C++ standard library (read: libc++). See out/msan above.

Test everything which uses compiler-rt/lib/sanitizer_common/:

check-{asan,cfi,dfsan,fuzzer,gwp_asan,hwasan,lsan,memprof,msan,lsan,sanitizer,tsan,ubsan,ubsan-minimal,xray}

Build the internal symbolizer:

cd /tmp/Rel
CLANG=/tmp/Rel/bin/clang ~/llvm/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh /tmp/Rel/lib/clang/18/lib/x86_64-unknown-linux-gnu/

Other systems

Chromium testing uses Ubuntu 16.04

apt install software-properties-common
add-apt-repository ppa:deadsnakes/ppa
apt install python3.7  # lit needs Python>=3.6
apt install libpfm4-dev  # some llvm-exegesis features

Android

https://github.com/google/sanitizers/wiki/SanitizerBotReproduceBuild mentions a multi-stage build instruction. Prerequisite: apt install adb jq (adb for Android).

# Clone llvm-zorg.
# Ensure `adb devices` lists a device.

mkdie -p scratch_dir && cd scratch_dir

# Comment out `rm_dirs compiler_rt_build_android_$_arch llvm_build_android_$_arch` in llvm-zorg/zorg/buildbot/builders/sanitizers/buildbot_android_functions.sh
# Comment out `clobber` to not delete the previous build directories.
BUILDBOT_MONO_REPO_PATH=~/llvm ../llvm-zorg/zorg/buildbot/builders/sanitizers/buildbot_android.sh
  • android_ndk: downloaded Android NDK. The toolchain is at android_ndk/toolchains/llvm/prebuilt/linux-x86_64/
  • llvm-project: used for llvm_build0. This repo is cloned even if you specify BUILDBOT_MONO_REPO_PATH
  • llvm_build0: build stage-1 clang;compiler-rt;lld at the latest stable release tag (see build_clang_at_release_tag) using a system compiler
  • llvm_build64: build stage-2 clang;lld using llvm_build0/bin/clang
  • llvm_build_android_aarch64: build stage-3 llvm using llvm_build64/bin/clang. The CFLAGS includes --target=aarch64-linux-android24 --sysroot=$ANDROID_TOOLCHAIN/sysroot --gcc-toolchain=$ANDROID_TOOLCHAIN -B$ANDROID_TOOLCHAIN
  • compiler_rt_build_android_aarch64: build stage-3 compiler-rt (standalone) using llvm_build64/bin/clang

After a compiler_rt_build_android_* directory is available, you may skip buildbot_android.sh and run ANDROID_SERIAL=$(adb devices | grep 'device$' | cut -f1) ninja -C compiler_rt_build_android_aarch64 check-all instead.

Debian 10 i386

sudo debootstrap --arch i386 buster buster.i386
sudo mount -t proc /proc buster.i386/proc
sudo chroot buster.i386
git rebase -i --exec 'arc diff HEAD^' origin/main

LSP

% cat ~/bin/tblgen-lsp-server
#!/bin/zsh
~/llvm/out/release/bin/tblgen-lsp-server --tablegen-compilation-database=/tmp/Rel/tablegen_compile_commands.yml "$@"
⚠️ **GitHub.com Fallback** ⚠️