Last active
November 28, 2025 02:51
-
-
Save hoyhoy/492cf3077239baececb6b838bf620d39 to your computer and use it in GitHub Desktop.
LLVM 21.1.6 Two Stage Build Script for MacOS 15.7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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