Files
serenity/Toolchain/BuildJakt.sh
Ali Mohammad Pur ffb9ea56dc Meta+Userland: Update Jakt to latest
This version fixes clang 22 errors on build.
2026-03-30 13:00:52 +02:00

273 lines
9.2 KiB
Bash
Executable File

#!/usr/bin/env bash
set -eo pipefail
# This file will need to be run in bash, for now.
# === CONFIGURATION AND SETUP ===
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# serenity | lagom
FINAL_TARGET="${1:-serenity}"
. "${DIR}/../Meta/shell_include.sh"
exit_if_running_as_root "Do not run BuildJakt.sh as root, your Build directory will become root-owned"
ARCHES=("x86_64" "aarch64" "riscv64")
PREFIX="$DIR/Local/jakt"
VALID_TOOLCHAINS=()
for ARCH in "${ARCHES[@]}"; do
TARGET="$ARCH-serenity"
eval "BUILD_GNU_${ARCH}=\"$DIR/../Build/$ARCH\""
eval "BUILD_CLANG_${ARCH}=\"$DIR/../Build/${ARCH}clang\""
eval "CXX_GNU_${ARCH}=\"$DIR/Local/$ARCH/bin/$TARGET-g++\""
eval "CXX_CLANG_${ARCH}=\"$DIR/Local/clang/bin/$TARGET-clang++\""
eval "RANLIB_GNU_${ARCH}=\"$DIR/Local/$ARCH/bin/$TARGET-ranlib\""
eval "RANLIB_CLANG_${ARCH}=\"$DIR/Local/clang/bin/llvm-ranlib\""
VAR_CXX_GNU="CXX_GNU_${ARCH}"
if [ -x "${!VAR_CXX_GNU}" ]; then
VALID_TOOLCHAINS+=("GNU;${ARCH}")
fi
VAR_CXX_CLANG="CXX_CLANG_${ARCH}"
if [ -x "${!VAR_CXX_CLANG}" ]; then
VALID_TOOLCHAINS+=("CLANG;${ARCH}")
fi
done
if [ "$FINAL_TARGET" = serenity ] && [ "${#VALID_TOOLCHAINS[@]}" -eq 0 ]; then
die "Need to build at least one C++ toolchain (either GNU or Clang) before BuildJakt.sh can succeed"
fi
REALPATH="realpath"
SYSTEM_NAME="$(uname -s)"
NPROC=$(get_number_of_processing_units)
if [ "$SYSTEM_NAME" = "OpenBSD" ]; then
REALPATH="readlink -f"
export CXX=eg++
elif [ "$SYSTEM_NAME" = "Darwin" ]; then
REALPATH="perl -e 'use Cwd \"abs_path\"; print abs_path(shift)'"
fi
if command -v ginstall &>/dev/null; then
INSTALL=ginstall
else
INSTALL=install
fi
buildstep() {
NAME=$1
shift
"$@" 2>&1 | sed $'s|^|\x1b[34m['"${NAME}"$']\x1b[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] ' "$@"
}
mkdir -p "$DIR/Tarballs"
JAKT_COMMIT_HASH="6f6c9e9005683b0c1cf59f6282a1bb15770e1c92"
JAKT_NAME="jakt-${JAKT_COMMIT_HASH}"
JAKT_TARBALL="${JAKT_NAME}.tar.gz"
JAKT_GIT_URL="https://github.com/serenityos/jakt"
function already_available() {
local TOOLCHAIN="$1"; shift
local ARCH="$1"; shift
HASH_FILE="${PREFIX}/.jakt-${TOOLCHAIN}-${ARCH}.hash"
if [ -f "$HASH_FILE" ] && [ "$JAKT_COMMIT_HASH" = "$(<"$HASH_FILE")" ]; then
# Make sure we have a binary.
if ! [ -e "$PREFIX/bin/jakt" ]; then
# We don't actually have anything, the file lied.
echo "$HASH_FILE exists and says we have $JAKT_COMMIT_HASH, but there's no associated binary; rebuilding!"
rm "$HASH_FILE"
fi
fi
if [ -f "$HASH_FILE" ] && [ "$JAKT_COMMIT_HASH" = "$(<"$HASH_FILE")" ]; then
echo "Already have the latest compiler built; remove $HASH_FILE to force-rebuild."
return 0
elif [ -f "$HASH_FILE" ]; then
echo "Expected $JAKT_COMMIT_HASH but found $(<"$HASH_FILE")"
return 1
else
echo "Expected $JAKT_COMMIT_HASH but found none (for $TOOLCHAIN $ARCH)"
return 1
fi
}
function stamp() {
local TOOLCHAIN="$1"; shift
local ARCH="$1"; shift
echo "$JAKT_COMMIT_HASH" > "${PREFIX}/.jakt-$TOOLCHAIN-$ARCH.hash"
}
# === DEPENDENCIES ===
buildstep dependencies echo "Checking whether 'ninja' is available..."
if ! command -v "${NINJA:-ninja}" >/dev/null; then
buildstep dependencies echo "Please make sure to install Ninja (for the '${NINJA:-ninja}' tool)."
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 (for the 'cmake' tool)."
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
# === DOWNLOAD AND PATCH ===
pushd "$DIR/Tarballs"
if [ ! -d "${JAKT_NAME}" ]; then
echo "Downloading jakt..."
rm -f "$JAKT_TARBALL"
curl -L --output "$JAKT_TARBALL" "$JAKT_GIT_URL/archive/$JAKT_COMMIT_HASH.tar.gz"
echo "Extracting jakt..."
tar -xzf "${JAKT_TARBALL}"
else
echo "Using existing Jakt source directory"
fi
popd
# === COMPILE AND INSTALL ===
if ! already_available local host; then
rm -rf "$PREFIX"
mkdir -p "$PREFIX"
rm -rf "$DIR/Build/jakt"
mkdir -p "$DIR/Build/jakt"
pushd "$DIR/Build/jakt"
echo "XXX configure jakt"
buildstep "jakt/configure" cmake -S "$DIR/Tarballs/${JAKT_NAME}" -B . \
-DSERENITY_SOURCE_DIR="$DIR/.." \
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
-DCMAKE_BUILD_TYPE=Release \
-GNinja \
|| exit 1
echo "XXX build jakt"
buildstep_ninja "jakt/build" ninja jakt_stage1
echo "XXX install jakt"
buildstep_ninja "jakt/install" ninja install
popd
fi
stamp local host
if ! [ "$FINAL_TARGET" = serenity ]; then
echo "Done creating jakt toolchain for host"
exit 0
fi
build_for() {
TOOLCHAIN="$1"
ARCH="$2"
TARGET="$ARCH-serenity"
JAKT_TARGET="$ARCH-unknown-serenity-unknown"
current_build="BUILD_${TOOLCHAIN}_${ARCH}"
current_cxx="CXX_${TOOLCHAIN}_${ARCH}"
current_ranlib="RANLIB_${TOOLCHAIN}_${ARCH}"
BUILD="${!current_build}"
TARGET_CXX="${!current_cxx}"
TARGET_RANLIB="${!current_ranlib}"
if already_available "$TOOLCHAIN" "$ARCH"; then
return 0
fi
# On at least OpenBSD, the path must exist to call realpath(3) on it
if [ ! -d "$BUILD" ]; then
mkdir -p "$BUILD"
fi
BUILD=$(eval "$REALPATH" "$BUILD")
echo "XXX building jakt support libs in $BUILD with $TARGET_CXX"
SYSROOT="$BUILD/Root"
echo SYSROOT is "$SYSROOT"
rm -rf "$DIR/Build/jakt-$TOOLCHAIN-$ARCH"
mkdir -p "$DIR/Build/jakt-$TOOLCHAIN-$ARCH"
pushd "$DIR/Build/jakt-$TOOLCHAIN-$ARCH"
echo "XXX serenity libc headers"
mkdir -p "$BUILD"
pushd "$BUILD"
mkdir -p Root/usr/include/
SRC_ROOT=$(eval "$REALPATH" "$DIR"/..)
FILES=$(find \
"$SRC_ROOT"/AK \
"$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 header in $FILES; do
target=$(echo "$header" | sed \
-e "s|$SRC_ROOT/AK/|AK/|" \
-e "s|$SRC_ROOT/Userland/Libraries/LibC||" \
-e "s|$SRC_ROOT/Kernel/|Kernel/|" \
-e "s|$SRC_ROOT/Userland/Libraries/LibELF/|LibELF/|" \
-e "s|$SRC_ROOT/Userland/Libraries/LibRegex/|LibRegex/|")
buildstep "system_headers" mkdir -p "$(dirname "Root/usr/include/$target")"
buildstep "system_headers" "$INSTALL" "$header" "Root/usr/include/$target"
done
unset SRC_ROOT
popd
echo "XXX build jakt support libs"
rm -fr "$SYSROOT/usr/local/lib/$JAKT_TARGET"
buildstep "jakt/support/build/$TOOLCHAIN" "$PREFIX/bin/jakt" cross \
--only-support-libs \
--install-root "$PREFIX/usr/local" \
--target-triple "$JAKT_TARGET" \
--target-links-ak \
-C "$TARGET_CXX" \
-O \
-J "$NPROC"
buildstep "jakt/support/build/$TOOLCHAIN/ranlib" "$TARGET_RANLIB" "$PREFIX/usr/local/lib/$JAKT_TARGET/libjakt_runtime_$JAKT_TARGET.a"
buildstep "jakt/support/build/$TOOLCHAIN/ranlib" "$TARGET_RANLIB" "$PREFIX/usr/local/lib/$JAKT_TARGET/libjakt_main_$JAKT_TARGET.a"
popd
}
for TOOLCHAIN_AND_ARCH in "${VALID_TOOLCHAINS[@]}"; do
IFS=';' read -r TOOLCHAIN ARCH <<< "$TOOLCHAIN_AND_ARCH"
buildstep "build/$TOOLCHAIN/$ARCH" build_for "$TOOLCHAIN" "$ARCH"
done
for TOOLCHAIN_AND_ARCH in "${VALID_TOOLCHAINS[@]}"; do
IFS=';' read -r TOOLCHAIN ARCH <<< "$TOOLCHAIN_AND_ARCH"
stamp "$TOOLCHAIN" "$ARCH"
done
echo "Done creating jakt toolchain for targets " "${VALID_TOOLCHAINS[@]}"