Last active
January 6, 2022 07:49
-
-
Save hamsham/47702917cfe35a1ee70051143675c8bb to your computer and use it in GitHub Desktop.
Build script to check-out and compile LLVM/Clang
This file contains 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 | |
set -euo pipefail | |
# This script follows the instructions for building Clang, from the LLVM | |
# documentation here: https://llvm.org/docs/GettingStarted.html#requirements | |
CLANG_RELEASE_LATEST=13.0.0 | |
CLANG_GIT_REPO=https://github.com/llvm/llvm-project.git | |
function verify_prerequisites() | |
{ | |
# Required executables listed from step 2 of the online manual | |
echo "Checking for prerequisite build tools..." | |
function _check_exe() | |
{ | |
local exeName=$(which "$1" 2> /dev/null) | |
if [[ -z "$exeName" ]]; then | |
echo -e "Error: Unable to find $1." | |
exit 1 | |
fi | |
echo -e "\tFound $1: $exeName" | |
} | |
_check_exe make | |
_check_exe python3 | |
_check_exe cmake | |
_check_exe bzip2 | |
_check_exe bunzip2 | |
_check_exe gzip | |
_check_exe gunzip | |
_check_exe tar | |
_check_exe zip | |
_check_exe unzip | |
# Required libraries | |
echo "Checking for prerequisite libraries..." | |
function _check_lib() | |
{ | |
local libName=$(ldconfig -p | grep "lib$1\.so[[:space:]]") | |
if [[ -z "$libName" ]]; then | |
echo -e "Error: Unable to find lib$1." | |
exit 1 | |
fi | |
echo -e "\tFound $1: $(echo "$libName" | awk '{print $4}')" | |
} | |
_check_lib z | |
echo "" | |
} | |
function verify_release_num() | |
{ | |
# Git branches use only a single digit in their name. Tagged releases use | |
# the MAJOR.MINOR.PATCH naming convention. Here, we validate only the | |
# MAJOR.MINOR.PATCH to avoid checking-out non-release branches. We'll need | |
# to rely on Git to error on invalid tag names later on. | |
local versionNum=$(echo "$1" | grep -E '^([1-9]+)\.([0-9]+)\.([0-9]+)$') | |
if [[ -z "$versionNum" ]]; then | |
echo "Error: Invalid version string for LLVM tagged branch. The version number must use the 'MAJOR.MINOR.PATCH' naming scheme." | |
exit 1 | |
fi | |
echo "LLVM version to clone: $versionNum" | |
echo "" | |
} | |
function get_source_dir_name() | |
{ | |
local llvmVersion="$1" | |
realpath "$workingDir/clang-$llvmVersion"-src | |
} | |
function get_build_dir_name() | |
{ | |
local llvmVersion="$1" | |
realpath "$workingDir/clang-$llvmVersion" | |
} | |
function clone_llvm() | |
{ | |
local llvmVersion="$1" | |
local llvmBranch="llvmorg-$llvmVersion" | |
local workingDir="$2" | |
local sourceDir=$(get_source_dir_name "$llvmVersion") | |
mkdir -p "$workingDir" | |
echo "Cloning LLVM $llvmVersion" | |
if [[ -d "$sourceDir" ]]; then | |
pushd "$sourceDir" | |
set +e | |
git status 2>&1 > /dev/null | |
local exit_status=$? | |
set -e | |
popd | |
if [[ exit_status -ne 0 ]]; then | |
echo "A non-source-controlled directory is located at $sourceDir. Please remove this directory and try again." | |
exit 1 | |
fi | |
else | |
git clone --depth 1 --branch "$llvmBranch" "$CLANG_GIT_REPO" "$sourceDir" | |
fi | |
echo "Updating local LLVM branch for $llvmVersion" | |
pushd "$sourceDir" | |
git checkout -- . | |
git pull --rebase | |
popd | |
echo "" | |
} | |
function configure_llvm() | |
{ | |
local llvmVersion="$1" | |
local sourceDir=$(get_source_dir_name "$llvmVersion") | |
local buildDir=$(get_build_dir_name "$llvmVersion") | |
local workingDir="$2" | |
local installPrefix="$3" | |
# Search for all top-level projects to build | |
local subProjects=$(find "$sourceDir" -mindepth 1 -maxdepth 2 -type f -name CMakeLists.txt -exec dirname {} \; | grep -v test | sed -E 's/.+\///' | tr '\n' ';') | |
mkdir -p "$buildDir" | |
echo "Building sub-projects: $subProjects" | |
set +e | |
cmake \ | |
-S "$sourceDir/llvm" \ | |
-B "$buildDir" \ | |
-DCMAKE_INSTALL_PREFIX="$installPrefix" \ | |
-DCMAKE_BUILD_TYPE=Release \ | |
-DLLVM_TARGETS_TO_BUILD="X86;AArch64;ARM;Mips;WebAssembly;NVPTX;AMDGPU;PowerPC;SystemZ" \ | |
-DLLVM_ENABLE_DOXYGEN=FALSE \ | |
-DLLVM_ENABLE_SPHINX=FALSE \ | |
-DLLVM_OPTIMIZED_TABLEGEN=TRUE \ | |
-DLLVM_ENABLE_PROJECTS="$subProjects" | |
local status=$? | |
set -e | |
if [[ $status -ne 0 ]]; then | |
echo "An error occurred while compiling LLVM." | |
exit 1 | |
fi | |
echo "" | |
} | |
function make_llvm() | |
{ | |
local llvmVersion="$1" | |
local buildDir=$(get_build_dir_name "$llvmVersion") | |
set +e | |
cmake --build "$buildDir" --config Release | |
local status=$? | |
set -e | |
if [[ $status -ne 0 ]]; then | |
echo "An error occurred while compiling LLVM." | |
exit 1 | |
fi | |
echo "" | |
} | |
function print_usage() | |
{ | |
echo "USAGE:" | |
echo -e "\t-h,--help Prints this message then exits." | |
echo -e "\t-r,--release Sets the release branch of Clang to clone from git." | |
echo -e "\t-d,--directory Path of the top-level directory where Clang will be checked-out and built (defaults to the current working directory)." | |
echo -e "\t-p,--prefix Specifies the installation prefix (note: 'make install' must be run manually outside of this script)." | |
echo "" | |
} | |
function main() | |
{ | |
local releaseVer="$CLANG_RELEASE_LATEST" | |
local workingDir=$(pwd) | |
local prefix="/opt" | |
set +u | |
while [ -n "$1" ]; do | |
case "$1" in | |
-h | --help) | |
print_usage | |
exit | |
;; | |
-r | --release) | |
shift | |
releaseVer="$1" | |
;; | |
-d | --directory) | |
shift | |
workingDir="$1" | |
;; | |
-p | --prefix) | |
shift | |
prefix="$1" | |
;; | |
*) | |
echo "Unknown parameter '$1'" | |
print_usage | |
exit 1 | |
;; | |
esac | |
shift | |
done | |
set -u | |
verify_prerequisites | |
verify_release_num "$releaseVer" | |
clone_llvm "$releaseVer" "$workingDir" | |
configure_llvm "$releaseVer" "$workingDir" "$prefix" | |
make_llvm "$releaseVer" | |
} | |
main $@ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment