Skip to content

Instantly share code, notes, and snippets.

@hoyhoy
Last active November 28, 2025 02:51
Show Gist options
  • Select an option

  • Save hoyhoy/492cf3077239baececb6b838bf620d39 to your computer and use it in GitHub Desktop.

Select an option

Save hoyhoy/492cf3077239baececb6b838bf620d39 to your computer and use it in GitHub Desktop.
LLVM 21.1.6 Two Stage Build Script for MacOS 15.7
#!/usr/bin/env bash
# Bash script to complile LLVM
# @hoyhoy
# 11/18/2025
# Installs to /opt/llvm-${LLVM_VERSION} i.e. /opt/llvm-21.1.6
# and then symbolically link /opt/llvm-latest to /opt/llvm-21.1.6
# This script automatically detects the current version
# if you checkout a release tag -- i.e.
# git checkout llvmorg-21.1.6
LLVM_INSTALL_PREFIX="/opt/llvm"
# apple-clang is in /usr if you're starting with Xcode.
# Xcode, or wherever your latest llvm is deployed...
# This is the compiler used to compile clang.
# It's possible to use a recent LLVM instead of
# AppleClang here, but there can be some problems with
# the compiler-rt if you do that.
STAGE_ONE_COMPILER=/usr
STAGE_ONE_COMPILER_BIN="${STAGE_ONE_COMPILER}/bin"
if [[ ! -d "${STAGE_ONE_COMPILER_BIN}" ]]; then
display_banner fail "could not find ${STAGE_ONE_COMPILER_BIN}"
fi
optimized_compile_flags="-O3 -march=native -mtune=native -funroll-loops -finline-functions -Wno-everything"
llvm_arch=$(uname -m)
llvm_triple="${llvm_arch,,}-apple-darwin"
# on rhel and fedora, the llvm libs are in weird places..
# llvm_lib=/usr/lib64/llvm20/lib64
# CCACHE=/opt/bin/ccache
if [[ "$(uname)" == "Linux" ]]; then
declare -gx CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
else
declare -gx CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.ncpu)
fi
declare -gx CTEST_PARALLEL_LEVEL=${CMAKE_BUILD_PARALLEL_LEVEL}
declare -gx NUMCPUS=${CMAKE_BUILD_PARALLEL_LEVEL}
display_banner() {
if [[ "${SUPPRESS_BANNER}" == "yes" ]]; then
return
fi
# Get terminal width
local banner_length=$(($(tput cols)))
# Set minimum banner length
if (( banner_length < 40 )); then
return # Don't display if terminal is too small
fi
local adjust=0
# Allow override if provided
if [[ -n "${3:-}" ]]; then
adjust="${3:-}"
fi
# Colors
red='\033[0;31m'
green='\033[0;32m'
white='\033[0;97m'
lightmagenta='\033[0;35m'
lightfaintgray='\033[2;90m'
darkyellow='\033[0;33m'
dimyellow='\033[2;33m'
nc='\033[0m'
local banner_type="${1:-}"
local message="${2:-}"
# Calculate widths
local line_width=$((banner_length - 2))
local max_message_length=$((banner_length - 6))
local text_width=$((banner_length - 6 + adjust))
# Truncate message if too long
if (( ${#message} > max_message_length )); then
message="${message:0:${max_message_length}}"
fi
local text_color="${white}"
local banner_color="${lightfaintgray}"
local icon=""
local icon_color=""
# Set banner style based on type
if [[ "${banner_type}" == "fail" ]]; then
banner_color="${red}"
icon="" # nf-fa-times_circle
icon_color="${red}"
elif [[ "${banner_type}" == "warning" ]]; then
banner_color="${dimyellow}"
icon="" # nf-fa-exclamation_triangle
icon_color="${darkyellow}"
elif [[ "${banner_type}" == "success" ]]; then
banner_color="${green}"
icon="" # nf-fa-check_circle
icon_color="${green}"
elif [[ "${banner_type}" == "highlight" ]]; then
banner_color="${lightmagenta}"
icon="" # nf-fa-star
icon_color="${lightmagenta}"
elif [[ "${banner_type}" == "status" ]]; then
banner_color="${lightfaintgray}"
icon="" # nf-fa-info_circle
icon_color="${lightfaintgray}"
fi
# Top border
printf "${banner_color}╭"
printf '─%.0s' $(seq 1 ${line_width})
printf "╮\n"
# Content line
printf "${banner_color}│ ${icon_color}${icon}${text_color} %${text_width}s ${banner_color}│\n" "${message}"
# Bottom border
printf "╰"
printf '─%.0s' $(seq 1 ${line_width})
printf "╯${nc}\n"
}
path_remove() {
local var_name="${2:-PATH}"
local var_value="${!var_name}"
# Delete path by parts so we can never accidentally remove sub paths
if [[ "$var_value" == "${1:-}" ]]; then
var_value="" ;
fi
var_value=${var_value//":${1:-}:"/":"} # delete any instances in the middle
var_value=${var_value/#"${1:-}:"/} # delete any instance at the beginning
var_value=${var_value/%":${1:-}"/} # delete any instance in the at the end
declare -gx ${var_name}="$var_value"
}
path_remove_first() {
local var_name="${2:-PATH}"
local var_value="${!var_name:-}"
local path_to_remove="${1:-}"
if [[ -z "${path_to_remove}" ]]; then
display_banner fail "nothing to remove from PATH!"
fi
if [[ "$var_value" == "${path_to_remove}" ]]; then
# PATH consists only of this entry
declare -gx ${var_name}=""
elif [[ "$var_value" == "${1:-}:"* ]]; then
# Path is at the beginning, remove it and the trailing colon
declare -gx ${var_name}="${var_value#"${path_to_remove}:"}"
fi
}
path_remove_glob() {
local pattern="${1:-}"
local var_name="${2:-PATH}"
local var_value="${!var_name:-}"
local IFS=':'
# Collect paths matching the pattern
for path in ${var_value}; do
if [[ ${path} == ${pattern} ]]; then
path_remove "${path}" "${var_name}"
fi
done
}
path_add() {
local var_name="${2:-PATH}"
local var_value"=${!var_name:-}"
local dir_name="${1:-}"
if [[ -d "${dir_name}" ]] && [[ ":$var_value:" != *":${dir_name}:"* ]]; then
declare -gx ${var_name}="${var_value:+"$var_value:"}${dir_name}"
fi
}
path_prepend() {
local var_name=${2:-PATH}
local var_value=${!var_name}
if [[ -d "${1:-}" ]] && [[ ":$var_value:" != *":${1:-}:"* ]]; then
declare -gx ${var_name}="${1:-}${var_value:+":$var_value"}"
fi
}
path_remove "${STAGE_ONE_COMPILER_BIN}"
path_prepend "${STAGE_ONE_COMPILER_BIN}"
unset_sanitizer_envirornment() {
unset ASAN_OPTIONS
unset MSAN_OPTIONS
unset TSAN_OPTIONS
unset UBSAN_OPTIONS
unset LSAN_OPTIONS
unset SYMBOLIZER_PATH
unset ASAN_SYMBOLIZER_PATH
unset TSAN_SYMBOLIZER_PATH
unset MSAN_SYMBOLIZER_PATH
unset UBSAN_SYMBOLIZER_PATH
unset LSAN_SYMBOLIZER_PATH
unset LSAN_OPTIONS
}
unset_compiler_environment() {
unset LD_LIBRARY_PATH
unset DYLD_LIBRARY_PATH
unset LIBRARY_PATH
unset LIBPATH
unset CFLAGS
unset CXXFLAGS
unset CPPFLAGS
unset PKG_CONFIG
unset LDFLAGS
unset CPLUS_INCLUDE_PATH
unset CPATH
unset CPLUS_INCLUDE_PATH
unset CC
unset CXX
unset LD
unset AR
unset AS
unset NM
unset RANLIB
unset LINKER
unset LLVM_ROOT
unset LLVM_DIR
unset LLVM_PATH
unset LLVM_LIB
unset LD
unset GCC_ROOT
unset LIPO
unset PKG_CONFIG
unset PKG_CONFIG_PATH
unset GTKDOCIZE
unset OPENSSLDIR
unset LZ4_CFLAG
unset LZ4_LIBS
unset NETTLE_LIBS
unset NETTLE_CFLAGS
unset HOGWEED_LIBS
unset HOGWEED_CFLAGS
unset CCACHE_COMPILER
unset CONAN_LLVM_MSAN_IGNORELIST
unset OPENSSL_LIBS
unset OPENSSL_CFLAGS
unset OPENSSLDIR
unset OPENSSL_ROOT_DIR
unset OPENSSL_LIB_DIR
unset OPENSSL_INCLUDE_DIR
unset CONAN_GCC_ROOT
unset CONAN_GCC_EXTRA_LIBDIRS
unset GCC_VERSION
unset OBJCOPY
unset OBJDUMP
unset STRIP
unset CONFIG_SITE
unset CONAN_LLVM_ROOT
unset CONAN_COMPILER_VERSION
unset CONAN_COMPILER
unset CONAN_BUILD_TYPE
unset CLANG_ROOT
unset CLANG_BIN
unset CLANG_LIB
}
cmake_compiler_settings_array() {
local -n result_array=$1
result_array=(
-DCMAKE_C_COMPILER:FILEPATH=${CC}
-DCMAKE_CXX_COMPILER:FILEPATH=${CXX}
-DCMAKE_RANLIB:FILEPATH=${RANLIB}
-DCMAKE_AR:FILEPATH=${AR}
# llvm needs the "clang" binary for the assembler, not llvm-as
-DCMAKE_ASM_COMPILER:FILEPATH=${CC}
-DCMAKE_LINKER:FILEPATH=${LD}
-DCMAKE_NM:FILEPATH=${NM}
-DCMAKE_LIPO:FILEPATH=${LIPO}
-DCMAKE_OBJCOPY:FILEPATH=${OBJCOPY}
-DCMAKE_OBJDUMP:FILEPATH=${OBJDUMP}
-DCMAKE_STRIP:FILEPATH=${STRIP}
-DCMAKE_READELF:FILEPATH=${READELF}
)
}
cmake_compiler_status() {
for arg in "$@"; do
# Extract the path after the = sign
path="${arg#*=}"
if [[ -f "${path}" ]]; then
display_banner success "${arg}"
else
display_banner fail "${arg} (file not found)"
# exit 1
fi
done
}
configure_clang() {
unset_compiler_environment
unset_sanitizer_envirornment
local llvm_binaries=(as ar nm lipo objdump objcopy readelf strip ranlib symbolizer)
declare -gx CLANG_ROOT="${1:-}"
declare -gx CLANG_EXECUTABLE="${2:-}"
declare -gx CONAN_COMPILER=clang
declare -gx CONAN_COMPILER_NAME=llvm
local clang_lib="${3:-lib}"
if [[ "${clang_lib}" == /* ]]; then
declare -gx CLANG_LIB="${clang_lib}"
else
declare -gx CLANG_LIB="${CLANG_ROOT}/${clang_lib}"
fi
declare -gx CLANG_BIN="${CLANG_ROOT}/bin"
declare -gx LLVM_VERSION="${4:-}"
if [[ -n "${TMUX:-}" ]]; then
echo "${LLVM_VERSION}" > ${HOME}/.config/tmux/tmux-compiler-version
tmux refresh-client -S
fi
if [[ -f "${CLANG_BIN}/${CLANG_EXECUTABLE}" ]]; then
declare -gx CCACHE_COMPILER="${CLANG_BIN}/${CLANG_EXECUTABLE}"
elif [[ -f "${CLANG_BIN}/clang" ]]; then
declare -gx CCACHE_COMPILER="${CLANG_BIN}/clang"
else
display_banner fail "could not find clang binary."
exit
fi
if [[ -f "${CLANG_BIN}/lld" ]]; then
display_banner status "using lld!"
declare -gx LINKER_NAME="lld"
else
display_banner status "using ld!"
declare -gx LINKER_NAME="ld"
fi
declare -gx LD="${CLANG_BIN}/${LINKER_NAME}"
declare -gx LINKER="${CLANG_BIN}/${LINKER_NAME}"
declare -gx CC="${CLANG_BIN}/clang"
declare -gx CXX="${CLANG_BIN}/clang++"
for binary in "${llvm_binaries[@]}"; do
find_llvm_binary "${binary}"
done
declare -gx LLVM_DIR="${CLANG_ROOT}"
declare -gx LLVM_PATH="${CLANG_BIN}"
declare -gx LLVM_ROOT="${CLANG_ROOT}"
declare -gx CONAN_LLVM_ROOT="${CLANG_ROOT}"
declare -gx LLVM_LIB="${CLANG_LIB}"
path_remove_first "/usr/bin"
# redhat scl paths
path_remove_glob "/opt/rh/*"
path_remove_glob "${STAGE_ONE_COMPILER}/bin"
path_remove "${CLANG_BIN}"
path_prepend "${CLANG_BIN}"
}
find_llvm_binary() {
local binary_name="${1:-}"
local llvm_binary_path="${CLANG_BIN}/llvm-${binary_name}"
local binary_path="${CLANG_BIN}/${binary_name}"
local alt_binary_path="${STAGE_ONE_COMPILER}/bin/${binary_name}"
local llvm_alt_binary_path="${STAGE_ONE_COMPILER}/bin/llvm-${binary_name}"
local llvm_alt_alt_binary_path="/opt/bin/${binary_name}"
local var_name="${binary_name^^}"
# if no llvm symbolizer can be found...
local fallback_symbolizer="/usr/bin/addr2line"
if [[ -z "${var_name}" ]]; then
display_banner fail "var_name not set"
return 1
fi
if [[ -z "${CLANG_BIN}" ]]; then
display_banner fail "CLANG_BIN not set"
return 1
fi
if [[ "${var_name}" == "SYMBOLIZER" ]]; then
var_name="SYMBOLIZER_PATH"
fi
# display_banner status "var_name=${var_name}"
if [[ -f "${llvm_binary_path}" ]]; then
declare -gx ${var_name}="${llvm_binary_path}"
# display_banner status "found ${llvm_binary_path}"
elif [[ -f "${binary_path}" ]]; then
declare -gx ${var_name}="${binary_path}"
# display_banner status "found ${binary_path}"
elif [[ -f "${alt_binary_path}" ]]; then
declare -gx ${var_name}="${alt_binary_path}"
elif [[ -f "${llvm_alt_binary_path}" ]]; then
declare -gx ${var_name}="${llvm_alt_binary_path}"
elif [[ -f "${llvm_alt_binary_path}" ]]; then
declare -gx ${var_name}="${llvm_alt_binary_path}"
elif [[ -f "${llvm_alt_alt_binary_path}" ]]; then
declare -gx ${var_name}="${llvm_alt_binary_path}"
elif [[ "${var_name}" == "SYMBOLIZER_PATH" ]]; then
if [[ -f "${fallback_symbolizer}" ]]; then
declare -gx SYMBOLIZER_PATH="${fallback_symbolizer}"
fi
elif [[ "${binary_name}" != "readelf" ]] && [[ "${binary_name}" != "objcopy" ]]; then
display_banner fail "could not find ${binary_path}, ${llvm_binary_path}, ${alt_binary_path} or ${llvm_alt_binary_path}"
return 1
fi
}
llvm() {
clang_flags="${1:-}"
if [[ -d "${STAGE_ONE_COMPILER}" ]]; then
llvm_root="${STAGE_ONE_COMPILER}"
else
# use /usr/bin/clang...
llvm_root="/usr"
fi
version_string=$(${llvm_root}/bin/clang --version | head -n1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
IFS='.' read -r llvm_major llvm_minor llvm_revision <<< "${version_string}"
llvm_version=${llvm_major}.${llvm_minor}.${llvm_revision}
llvm_lib="${llvm_lib:-"${STAGE_ONE_COMPILER}"/lib}"
if [[ -d "${llvm_lib}" ]]; then
# TODO(hoyhoy): Possibly fixed in 22 where they
# use the $(uname -m)-apple-darwin triple for this now...
declare -gx llvm_lib=lib
else
echo "llvm_lib does not exist!"
exit 1
fi
configure_clang ${llvm_root} clang-${llvm_major} ${llvm_lib} ${llvm_version}
declare -gx CONAN_COMPILER_VERSION=${llvm_major}
if [[ "$(uname)" == "Linux" ]]; then
declare -gx CONAN_LLVM_MSAN_IGNORELIST="${HOME}/.msan-ignorelist"
fi
if [[ -n "${clang_flags}" ]]; then
declare -gx CFLAGS="${clang_flags}"
declare -gx CXXFLAGS="${clang_flags}"
fi
}
runtimes_only=false
llvm "${optimized_compile_flags}"
while getopts ":rl" opt; do
case $opt in
r)
runtimes_only=true
# Find the latest build-YYYY* directory for current year
BUILD_DIR=$(ls -dt build-$(date +%Y)* 2>/dev/null | head -n 1)
if [[ -z "$BUILD_DIR" ]]; then
echo "Error: No build-$(date +%Y)* directory found"
exit 1
fi
;;
l)
llvm
;;
\?)
display_banner fail "Invalid option: -$OPTARG"
exit 1
;;
esac
done
# Only set BUILD_DIR if it wasn't already set by the -r option
if [[ -z "$BUILD_DIR" ]]; then
BUILD_DIR=build-$(date +%Y-%m-%d-%H-%M-%S)
fi
display_banner success "Build Directory: ${BUILD_DIR}"
llvm_cmake="${PWD}/cmake/Modules/LLVMVersion.cmake"
# Check if input file exists
if [[ ! -f ${llvm_cmake} ]]; then
display_banner fail "Error: ${llvm_cmake} not found" >&2
exit 1
fi
LLVM_VERSION_MAJOR=$(perl -ne 'print $1 if /LLVM_VERSION_MAJOR\s+(\d+)/' ${llvm_cmake})
LLVM_VERSION_MINOR=$(perl -ne 'print $1 if /LLVM_VERSION_MINOR\s+(\d+)/' ${llvm_cmake})
LLVM_VERSION_PATCH=$(perl -ne 'print $1 if /LLVM_VERSION_PATCH\s+(\d+)/' ${llvm_cmake})
# Check that all variables are non-empty and contain only digits
if [[ -z "$LLVM_VERSION_MAJOR" || ! "$LLVM_VERSION_MAJOR" =~ ^[0-9]+$ ]]; then
display_banner fail "Error: Failed to parse LLVM_VERSION_MAJOR" >&2
exit 1
fi
if [[ -z "$LLVM_VERSION_MINOR" || ! "$LLVM_VERSION_MINOR" =~ ^[0-9]+$ ]]; then
display_banner fail "Error: Failed to parse LLVM_VERSION_MINOR" >&2
exit 1
fi
if [[ -z "$LLVM_VERSION_PATCH" || ! "$LLVM_VERSION_PATCH" =~ ^[0-9]+$ ]]; then
display_banner fail "Error: Failed to parse LLVM_VERSION_PATCH" >&2
exit 1
fi
# Check that minor version is >= 1
if (( LLVM_VERSION_MINOR < 1 )); then
display_banner fail "Error: LLVM minor version must be >= 1 (found: $LLVM_VERSION_MINOR)" >&2
exit 1
fi
display_banner status "Compiling LLVM Version: $LLVM_VERSION_MAJOR.$LLVM_VERSION_MINOR.$LLVM_VERSION_PATCH"
LLVM_VERSION_TO_COMPILE=${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}
LLVM_BIN="${LLVM_ROOT}/bin"
display_banner status "LLVM_BIN=${LLVM_BIN}"
LLVM_LIB="${LLVM_ROOT}/lib"
display_banner status "LLVM_LIB=${LLVM_LIB}"
INSTALL_PATH="${LLVM_INSTALL_PREFIX}-${LLVM_VERSION_TO_COMPILE}"
MACOS_SDK_ROOT=$(xcrun --show-sdk-path)
MACOS_VERSION=$(sw_vers -productVersion 2>&1 | perl -p -e 's/([^.]+)\.([^.]+)\..*/$1.$2/')
DARWIN_VERSION=$(uname -r)
if [[ ! "$DARWIN_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
display_banner fail "Error: Invalid Darwin version format: $DARWIN_VERSION (expected X.Y.Z)" >&2
exit 1
fi
display_banner success "Darwin version: $DARWIN_VERSION"
LLVM_CLANG_C_CONFIG_FILE_NAME="${llvm_triple}${DARWIN_VERSION}-clang.cfg"
LLVM_CLANG_CPP_CONFIG_FILE_NAME="${llvm_triple}${DARWIN_VERSION}-clang++.cfg"
if [[ -d ${INSTALL_PATH}/etc ]]; then
rm -f ${INSTALL_PATH}/etc/*.cfg
fi
security find-certificate -Z -p -c lldb_codesign /Library/Keychains/System.keychain >/dev/null 2>/dev/null || true
if [[ $? -eq 0 ]]; then
display_banner success "Found lldb_codesign certificate."
else
display_banner fail "Could not find lldb_codesign certificate. Adding to the local keystore."
lldb/script/macos-setup-codesign.sh || {
display_banner fail "Failed adding lldb_codesign certificate!"
display_banner fail "Exiting"
exit 1
}
fi
join_by() {
local IFS="${1:-}"; shift; echo "$*";
}
display_banner status "LLVM_TRIPLE=#{llvm_triple}"
display_banner status "LLVM_ROOT=${LLVM_ROOT}"
if [[ "${LINKER_NAME}" == "lld" ]]; then
declare -gx LDFLAGS="-fuse-ld=lld"
cmake_args+=(-DLLVM_ENABLE_LLD:BOOL=ON)
runtime_cmake_args=(-DLLVM_ENABLE_LLD:BOOL=ON)
display_banner status "LLD Enabled."
else
cmake_args+=(-DLLVM_ENABLE_LLD:BOOL=OFF)
runtime_cmake_args=(-DLLVM_ENABLE_LLD:BOOL=OFF)
display_banner status "LLD Disabled."
fi
if [[ "${runtimes_only}" != true ]]; then
echo ' ___ _____ _ ___ ___ ___ _ _ ___'
echo '/ __|_ _/_\ / __| __| / _ \| \| | __|'
echo '\__ \ | |/ _ \ (_ | _| | (_) | .` | _|'
echo '|___/ |_/_/ \_\___|___| \___/|_|\_|___|'
# I intentionally limit the path and move /usr/bin behind the stage one compiler..
# in theory,
cmake_args=(
-DCMAKE_BUILD_TYPE:STRING=Release
-DLLVM_ENABLE_RUNTIMES:STRING=""
-DLLVM_ENABLE_PROJECTS:STRING="clang;clang-tools-extra;lldb;lld"
-DCMAKE_MACOSX_RPATH:BOOL=ON
-DCMAKE_INSTALL_RPATH:FILEPATH="${INSTALL_PATH}/lib;${INSTALL_PATH}/lib/darwin"
-DCMAKE_SKIP_RPATH:BOOL=OFF
# -DLLVM_LOCAL_RPATH="${LLVM_ROOT}/lib;${LLVM_ROOT}/lib/darwin"
-DCMAKE_INSTALL_NAME_DIR:STRING="${INSTALL_PATH}/lib"
-DDEFAULT_SYSROOT:PATH=${MACOS_SDK_ROOT}
-DCMAKE_OSX_SYSROOT:PATH=${MACOS_SDK_ROOT}
# -DCMAKE_EXE_LINKER_FLAGS="-lc++abi -fuse-ld=${LD}"
# -DLLDB_BUILD_FRAMEWORK:BOOL=OFF
-DLLDB_USE_SYSTEM_DEBUGSERVER:BOOL=OFF
-DLLDB_ENABLE_LIBEDIT:BOOL=ON
-DLLDB_ENABLE_CURSES:BOOL=ON
-DCLANG_DEFAULT_CXX_STDLIB:STRING=libc++
-DCLANG_DEFAULT_RTLIB:STRING=compiler-rt
-DCLANG_DEFAULT_LINKER:STRING="${LINKER}"
-DCLANG_DEFAULT_UNWINDLIB=libunwind
-DLLVM_USE_STATIC_ZSTD:BOOL=ON
-DCMAKE_INSTALL_PREFIX:PATH="${INSTALL_PATH}"
-DCLANG_CONFIG_FILE_SYSTEM_DIR:PATH="${INSTALL_PATH}/etc"
-DLLVM_INSTALL_BINUTILS_SYMLINKS:BOOL=ON
-DLLVM_INSTALL_CCTOOLS_SYMLINKS:BOOL=ON
-DCLANG_INCLUDE_TESTS:BOOL=OFF
-DLLVM_INCLUDE_TESTS:BOOL=OFF
-DLLVM_BUILD_TOOLS:BOOL=ON
-DHAVE_CXX_ATOMICS64_WITHOUT_LIB:BOOL=ON
-DHAVE_CXX_ATOMICS_WITHOUT_LIB:BOOL=ON
-DLLVM_PARALLEL_COMPILE_JOBS:STRING=17
-DLLVM_PARALLEL_LINK_JOBS:STRING=2
-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING="${MACOS_VERSION}"
-DLLVM_ENABLE_RTTI:BOOL=ON
-DLLVM_ENABLE_FFI:BOOL=ON
-DLLVM_ENABLE_EH:BOOL=ON
)
cmake_compiler_settings_array compiler_settings
display_banner status "Using LLVM Version: ${LLVM_VERSION}"
cmake_compiler_status "${compiler_settings[@]}"
cmake_args+=("${compiler_settings[@]}")
if [[ -e "${CCACHE:-}" ]]; then
display_banner success "found ccache at ${CCACHE}"
cmake_args+=("-DCMAKE_C_COMPILER_LAUNCHER=${CCACHE}")
cmake_args+=("-DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE}")
fi
display_banner status "cmake args"
echo "$(join_by ';' "${cmake_args[@]}")"
display_banner status "Building ${LLVM_VERSION_TO_COMPILE}..."
cmake "${cmake_args[@]}" -S llvm -G Ninja -B "${BUILD_DIR}"
ninja -C "${BUILD_DIR}"
ninja -C "${BUILD_DIR}" install
fi
mkdir -p ${INSTALL_PATH}/etc
if [[ ! -f${INSTALL_PATH}/lib/clang/${LLVM_VERSION_MAJOR}/lib/darwin ]]; then
ln -fs ${INSTALL_PATH}/lib/clang/${LLVM_VERSION_MAJOR}/lib/darwin ${INSTALL_PATH}/lib/darwin
fi
cat >${INSTALL_PATH}/etc/${LLVM_CLANG_C_CONFIG_FILE_NAME} << EOF
-mtune=native -march=native
EOF
cat >${INSTALL_PATH}/etc/${LLVM_CLANG_CPP_CONFIG_FILE_NAME} << EOF
-mtune=native -march=native -fuse-ld=lld
EOF
BUILD_RUNTIMES_DIR=build-runtimes-$(date +%Y-%m-%d-%I-%M-%S)
mkdir ${BUILD_RUNTIMES_DIR}
display_banner status "Runtimes Build Directory: ${BUILD_RUNTIMES_DIR}"
declare -gx CLANG_ROOT=${INSTALL_PATH}
LLVM_BIN=${INSTALL_PATH}/bin
display_banner status "PATH=${PATH}"
declare -gx DYLD_LIBRARY_PATH=${LLVM_ROOT}/lib:${LLVM_ROOT}/lib/darwin
declare -gx CPATH="${CLANG_ROOT}/include"
echo ' ___ _____ _ ___ ___ _______ _____'
echo ' / __|_ _/_\ / __| __| |_ _\ \ / / _ \'
echo ' \__ \ | |/ _ \ (_ | _| | | \ \/\/ / (_) |'
echo ' |___/ |_/_/ \_\___|___| |_| \_/\_/ \___/'
runtime_vars=(
-DCMAKE_OSX_DEPLOYMENT_TARGET=${MACOS_VERSION}
)
runtime_cmake_args+=(
-DCMAKE_BUILD_TYPE:STRING=Release
-DLLVM_ENABLE_RUNTIMES:STRING="libcxx;libcxxabi;compiler-rt;libunwind"
-DLIBCXX_CXX_ABI:STRING=libc++abi
-DLIBCXXABI_USE_LLVM_UNWINDER:BOOL=OFF
-DLIBCXXABI_USE_COMPILER_RT:BOOL=ON
-DLLVM_ENABLE_LIBCXX:BOOL=ON
-DCLANG_CONFIG_FILE_SYSTEM_DIR:PATH="${INSTALL_PATH}/etc"
-DCMAKE_INSTALL_PREFIX:PATH="${INSTALL_PATH}"
-DCMAKE_MACOSX_RPATH:BOOL=ON
-DCMAKE_INSTALL_RPATH:FILEPATH="${INSTALL_PATH}/lib;${INSTALL_PATH}/lib/darwin"
-DLLVM_USE_STATIC_ZSTD:BOOL=ON
-DLLDB_USE_SYSTEM_DEBUGSERVER:BOOL=OFF
-DLLDB_ENABLE_LIBEDIT:BOOL=ON
-DLLDB_ENABLE_CURSES:BOOL=ON
-DLLVM_INSTALL_BINUTILS_SYMLINKS:BOOL=ON
-DLLVM_INSTALL_CCTOOLS_SYMLINKS:BOOL=ON
-DLLVM_BUILD_TOOLS:BOOL=ON
-DHAVE_CXX_ATOMICS64_WITHOUT_LIB:BOOL=ON
-DHAVE_CXX_ATOMICS_WITHOUT_LIB:BOOL=ON
-DLLVM_PARALLEL_COMPILE_JOBS:STRING=17
-DLLVM_PARALLEL_LINK_JOBS:STRING=2
-DCMAKE_C_FLAGS:STRING="${CFLAGS}"
-DCMAKE_CXX_FLAGS:STRING="${CXXFLAGS}"
-DLIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS=ON
-DCMAKE_EXE_LINKER_FLAGS:STRING="${LDFLAGS}"
-DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}"
-DCMAKE_MODULE_LINKER_FLAGS:STRING="${LDFLAGS}"
-DCLANG_DEFAULT_LINKER:STRING=lld
-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING="${MACOS_VERSION}"
-DDEFAULT_SYSROOT:PATH="${MACOS_SDK_ROOT}"
-DLLVM_CMAKE_DIR=${BUILD_DIR}/cmake/modules/CMakeFiles
-DClang_DIR=${INSTALL_PATH}/bin
-DLLVM_ROOT=${INSTALL_PATH}
-DRUNTIMES_CMAKE_ARGS:STRING=$(join_by ';' "${runtime_vars[@]}")
-DLIBCXXABI_INSTALL_LIBRARY:BOOL=ON
-DLIBUNWIND_ENABLE_SHARED:BOOL=ON
-DCOMPILER_RT_BUILD_BUILTINS:BOOL=ON
-DCOMPILER_RT_ENABLE_IOS:BOOL=OFF
-DCOMPILER_RT_ENABLE_WATCHOS:BOOL=OFF
-DCOMPILER_RT_ENABLE_TVOS:BOOL=OFF
-DCOMPILER_RT_ENABLE_MACCATALYST:BOOL=OFF
-DCOMPILER_RT_BUILD_LIBFUZZER:BOOL=ON
-DCOMPILER_RT_BUILD_MEMPROF:BOOL=ON
-DCOMPILER_RT_BUILD_PROFILE:BOOL=ON
-DCOMPILER_RT_BUILD_SANITIZERS:BOOL=ON
-DCOMPILER_RT_BUILD_XRAY:BOOL=ON
-DRUNTIMES_BUILD_ALLOW_DARWIN:BOOL=ON
-DLIBCXX_USE_COMPILER_RT:BOOL=ON
-DLIBCXX_CXX_ABI:STRING=libcxxabi
-DLIBCXX_USE_COMPILER_RT:BOOL=ON
-DLIBCXXABI_USE_COMPILER_RT:BOOL=ON
-DLIBCXX_HAS_GCC_S_LIB:BOOL=OFF
-DLIBUNWIND_USE_COMPILER_RT:BOOL=ON
-DLLVM_ENABLE_RTTI:BOOL=ON
-DLLVM_ENABLE_FFI:BOOL=ON
-DLLVM_ENABLE_EH:BOOL=ON
)
configure_clang ${CLANG_ROOT} clang-${LLVM_VERSION_MAJOR} lib ${LLVM_VERSION_TO_COMPILE}
cmake_compiler_settings_array runtime_compiler_settings
display_banner status "LLVM Version: ${LLVM_VERSION}"
cmake_compiler_status "${compiler_settings[@]}"
display_banner status "Runtimes: LLVM_ROOT=${LLVM_ROOT}"
display_banner status "Runtimes: LLVM_BIN=${LLVM_BIN}"
display_banner status "Runtimes: LINKER=${LINKER}"
runtime_cmake_args+=("${runtime_compiler_settings[@]}")
for i in ${runtime_compiler_settings[@]}; do
display_banner status "$i"
done
display_banner status "Runtime CMake Arguments"
echo "$(join_by ';' "${runtime_cmake_args[@]}")"
cmake "${runtime_cmake_args[@]}" -S runtimes -G Ninja -B "${BUILD_RUNTIMES_DIR}"
ninja -C "${BUILD_RUNTIMES_DIR}"
ninja -C "${BUILD_RUNTIMES_DIR}" install
custom_dsymutil="${INSTALL_PATH}/bin/dsymutil_no_warnings"
# dsymutil emits a lot of warnings...
# this is a custom script to suppress them
# I only use this for customer sanitizer builds to
# get clean symbol tables with msan and tsan...
cat >${custom_dsymutil} <<-EOF
#!/bin/sh
${INSTALL_PATH}/bin/dsymutil \$@ 2>/dev/null
EOF
chmod a+x ${custom_dsymutil}
codesign -s lldb_codesign --entitlements lldb/tools/debugserver/resources/debugserver-macosx-entitlements.plist -f ${INSTALL_PATH}/bin/debugserver
if [[ -e "${LLVM_INSTALL_PREFIX}-latest" ]]; then
rm -f "${LLVM_INSTALL_PREFIX}-latest"
fi
ln -fs ${INSTALL_PATH} "${LLVM_INSTALL_PREFIX}-latest"
if [[ -d "${INSTALL_PATH}/lib/clang/${LLVM_VERSION_MAJOR}" ]]; then
ln -fs ${INSTALL_PATH}/li ${INSTALL_PATH}/lib/clang/${LLVM_VERSION_MAJOR}
display_banner status "Created symlink to ${INSTALL_PATH}/lib/clang/${LLVM_VERSION_MAJOR}"
fi
display_banner status "Bult LLVM Version: $LLVM_VERSION_MAJOR.$LLVM_VERSION_MINOR.$LLVM_VERSION_PATCH successfully!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment