ladybird/Toolchain/BuildClang.sh
Timothy Flynn daa9e852c9 Toolchain+CI: Remove unused TRY_USE_LOCAL_TOOLCHAIN parameter
This was used to create a .tar of the built Clang toolchain, but now we
just upload the built toolchain artifacts (same as the GNU toolchain).
2024-05-15 15:20:29 -06:00

275 lines
8.2 KiB
Bash
Executable file

#!/usr/bin/env bash
set -eo pipefail
# === CONFIGURATION AND SETUP ===
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# shellcheck source=/dev/null
. "${DIR}/../Meta/shell_include.sh"
exit_if_running_as_root "Do not run BuildClang.sh as root, parts of your Toolchain directory will become root-owned"
echo "$DIR"
PREFIX="$DIR/Local/clang/"
BUILD="$DIR/../Build/"
USERLAND_ARCHS="x86_64"
ARCHS="$USERLAND_ARCHS aarch64 riscv64"
MD5SUM="md5sum"
REALPATH="realpath"
INSTALL="install"
SED="sed"
SYSTEM_NAME="$(uname -s)"
if [ "$SYSTEM_NAME" = "OpenBSD" ]; then
MD5SUM="md5 -q"
REALPATH="readlink -f"
export CC=egcc
export CXX=eg++
export LDFLAGS=-Wl,-z,notext
elif [ "$SYSTEM_NAME" = "FreeBSD" ]; then
MD5SUM="md5 -q"
elif [ "$SYSTEM_NAME" = "Darwin" ]; then
MD5SUM="md5 -q"
REALPATH="grealpath" # GNU coreutils
INSTALL="ginstall" # GNU coreutils
fi
NPROC=$(get_number_of_processing_units)
[ -z "$MAKEJOBS" ] && MAKEJOBS=${NPROC}
if [ ! -d "$BUILD" ]; then
mkdir -p "$BUILD"
fi
BUILD=$($REALPATH "$BUILD")
dev=
ci=
while [ "$1" != "" ]; do
case $1 in
--dev ) dev=1
;;
--ci ) ci=1
;;
esac
shift
done
if [ "$dev" = "1" ] && [ "$ci" = "1" ]; then
echo "Please only set one of --dev or --ci."
exit 1
fi
echo PREFIX is "$PREFIX"
mkdir -p "$DIR/Tarballs"
LLVM_VERSION="18.1.3"
LLVM_MD5SUM="4f2cbf1e35f9c9377c6c89e67364c3fd"
LLVM_NAME="llvm-project-$LLVM_VERSION.src"
LLVM_PKG="$LLVM_NAME.tar.xz"
LLVM_URL="https://github.com/llvm/llvm-project/releases/download/llvmorg-$LLVM_VERSION/$LLVM_PKG"
buildstep() {
NAME=$1
shift
"$@" 2>&1 | "$SED" $'s|^|\e[34m['"${NAME}"$']\e[39m |'
}
buildstep_ninja() {
# When ninja writes to a pipe, it strips ANSI escape codes and prints one line per buildstep.
# Instead, use NINJA_STATUS so that we get colored output from LLVM's build and fewer lines of output when running in a tty.
# ANSI escape codes in NINJA_STATUS are slightly janky (ninja thinks that "\e[34m" needs 5 output characters instead of 5, so
# its middle elision is slightly off; also it would happily elide the "\e39m" which messes up the output if the terminal is too
# narrow), but it's still working better than the alternative.
NAME=$1
shift
env NINJA_STATUS=$'\e[34m['"${NAME}"$']\e[39m [%f/%t] ' "$@"
}
# === DEPENDENCIES ===
buildstep dependencies echo "Checking whether Ninja is available..."
if ! command -v ninja >/dev/null; then
buildstep dependencies echo "Please make sure to install Ninja."
exit 1
fi
buildstep dependencies echo "Checking whether CMake is available..."
if ! command -v cmake >/dev/null; then
buildstep dependencies echo "Please make sure to install CMake."
exit 1
fi
buildstep dependencies echo "Checking whether 'patch' is available..."
if ! command -v patch >/dev/null; then
buildstep dependencies echo "Please make sure to install GNU patch."
fi
buildstep dependencies echo "Checking whether your C compiler works..."
if ! ${CC:-cc} -o /dev/null -xc - >/dev/null <<'PROGRAM'
int main() {}
PROGRAM
then
buildstep dependencies echo "Please make sure to install a working C compiler."
exit 1
fi
buildstep dependencies echo "Checking whether your C++ compiler works..."
if ! ${CXX:-c++} -o /dev/null -xc - >/dev/null <<'PROGRAM'
int main() {}
PROGRAM
then
buildstep dependencies echo "Please make sure to install a working C++ compiler."
exit 1
fi
link_lld=
buildstep dependencies echo "Checking whether the LLD linker is available..."
if ${CXX:-c++} -o /dev/null -fuse-ld=lld -xc - >/dev/null 2>/dev/null << 'PROGRAM'
int main() {}
PROGRAM
then
link_lld=1
buildstep dependencies echo "Using LLD for linking LLVM."
else
buildstep dependencies echo "LLD not found. Using the default linker."
fi
buildstep setup echo "Determining if LLVM should be built with -march=native..."
if [ "$ci" = "1" ]; then
# The toolchain cache is shared among all runners, which might have different CPUs.
buildstep setup echo "On a CI runner. Using the default compiler settings."
elif [ -z "${CFLAGS+x}" ] && [ -z "${CXXFLAGS+x}" ]; then
if ${CXX:-c++} -o /dev/null -march=native -xc - >/dev/null 2>/dev/null << 'PROGRAM'
int main() {}
PROGRAM
then
export CFLAGS="-march=native"
export CXXFLAGS="-march=native"
buildstep setup echo "Using -march=native for compiling LLVM."
else
buildstep setup echo "-march=native is not supported by the compiler. Using the default settings."
fi
else
buildstep setup echo "Using user-provided CFLAGS/CXXFLAGS."
fi
# === DOWNLOAD AND PATCH ===
pushd "$DIR/Tarballs"
md5=""
if [ -e "$LLVM_PKG" ]; then
md5="$($MD5SUM ${LLVM_PKG} | cut -f1 -d' ')"
echo "llvm md5='$md5'"
fi
if [ "$md5" != "$LLVM_MD5SUM" ] ; then
rm -f "$LLVM_PKG"
curl -LO "$LLVM_URL"
else
echo "Skipped downloading LLVM"
fi
patch_md5="$($MD5SUM "$DIR"/Patches/llvm/*.patch)"
if [ ! -d "$LLVM_NAME" ] || [ "$(cat $LLVM_NAME/.patch.applied)" != "$patch_md5" ]; then
if [ -d "$LLVM_NAME" ]; then
# Drop the previously patched extracted dir
rm -rf "${LLVM_NAME}"
fi
rm -rf "$DIR/Build/clang"
echo "Extracting LLVM..."
tar -xJf "$LLVM_PKG"
pushd "$LLVM_NAME"
if [ "$dev" = "1" ]; then
git init > /dev/null
git add . > /dev/null
git commit -am "BASE" > /dev/null
git am --keep-non-patch "$DIR"/Patches/llvm/*.patch > /dev/null
else
for patch in "$DIR"/Patches/llvm/*.patch; do
patch -p1 < "$patch" > /dev/null
done
fi
echo "$patch_md5" > .patch.applied
popd
else
echo "Using existing LLVM source directory"
fi
popd
# === COPY HEADERS ===
SRC_ROOT=$($REALPATH "$DIR"/..)
FILES=$(find \
"$SRC_ROOT"/Kernel/API \
"$SRC_ROOT"/Kernel/Arch \
"$SRC_ROOT"/Userland/Libraries/LibC \
"$SRC_ROOT"/Userland/Libraries/LibELF/ELFABI.h \
"$SRC_ROOT"/Userland/Libraries/LibRegex/RegexDefs.h \
-name '*.h' -print)
for arch in $ARCHS; do
mkdir -p "$BUILD/${arch}clang"
pushd "$BUILD/${arch}clang"
mkdir -p Root/usr/include/
for header in $FILES; do
target=$(echo "$header" | "$SED" \
-e "s|$SRC_ROOT/Kernel/|Kernel/|" \
-e "s|$SRC_ROOT/Userland/Libraries/LibC||" \
-e "s|$SRC_ROOT/Userland/Libraries/LibELF/|LibELF/|" \
-e "s|$SRC_ROOT/Userland/Libraries/LibRegex/|LibRegex/|")
buildstep "system_headers" "$INSTALL" -D "$header" "Root/usr/include/$target"
done
popd
done
unset SRC_ROOT
# === COMPILE AND INSTALL ===
rm -rf "$PREFIX"
mkdir -p "$PREFIX"
mkdir -p "$DIR/Build/clang"
pushd "$DIR/Build/clang"
mkdir -p llvm
pushd llvm
buildstep "llvm/configure" cmake "$DIR/Tarballs/$LLVM_NAME/llvm" \
-G Ninja \
-DSERENITY_x86_64-pc-serenity_SYSROOT="$BUILD/x86_64clang/Root" \
-DSERENITY_aarch64-pc-serenity_SYSROOT="$BUILD/aarch64clang/Root" \
-DSERENITY_riscv64-pc-serenity_SYSROOT="$BUILD/riscv64clang/Root" \
-DSERENITY_x86_64-pc-serenity_STUBS="$DIR/Stubs/x86_64" \
-DSERENITY_aarch64-pc-serenity_STUBS="$DIR/Stubs/aarch64" \
-DSERENITY_riscv64-pc-serenity_STUBS="$DIR/Stubs/riscv64" \
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
-DSERENITY_MODULE_PATH="$DIR/CMake" \
-C "$DIR/CMake/LLVMConfig.cmake" \
${link_lld:+"-DLLVM_ENABLE_LLD=ON"} \
${dev:+"-DLLVM_CCACHE_BUILD=ON"} \
${ci:+"-DLLVM_CCACHE_BUILD=ON"} \
${ci:+"-DLLVM_CCACHE_DIR=$LLVM_CCACHE_DIR"}
buildstep_ninja "llvm/build" ninja -j "$MAKEJOBS"
buildstep_ninja "llvm/install" ninja install/strip
popd
popd
pushd "$DIR/Local/clang/bin/"
ln -s ../../mold/bin/mold ld.mold
for arch in $ARCHS; do
ln -s clang "$arch"-pc-serenity-clang
ln -s clang++ "$arch"-pc-serenity-clang++
ln -s llvm-nm "$arch"-pc-serenity-nm
echo "--sysroot=$BUILD/${arch}clang/Root" > "$arch"-pc-serenity.cfg
done
popd