summaryrefslogtreecommitdiff
path: root/bootstrap.sh
diff options
context:
space:
mode:
Diffstat (limited to 'bootstrap.sh')
-rwxr-xr-xbootstrap.sh171
1 files changed, 171 insertions, 0 deletions
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100755
index 0000000..36fc599
--- /dev/null
+++ b/bootstrap.sh
@@ -0,0 +1,171 @@
+#!/bin/zsh -e
+
+BOOTSTRAP=$(pwd)/.bootstrap
+MICROARCH="skylake"
+PROCS=$(nproc)
+SOURCES=$(pwd)/.treetap/sources
+TARGET=x86_64-maple-linux-musl
+
+# Fetch sources required for a bootstrap
+./treetap fetch sources/busybox.spec
+./treetap fetch sources/linux.spec
+./treetap fetch sources/llvm.spec
+./treetap fetch sources/musl.spec
+
+# Simplified filesystem heirarchy with symlinks for compatibility
+mkdir -p $BOOTSTRAP/root/{bin,boot/EFI/BOOT,dev,etc,home,lib,proc,run,sys,tmp,usr/{include,share},var/{cache,lib,log,spool,tmp}}
+ln -sf bin $BOOTSTRAP/root/sbin
+ln -sf ../bin $BOOTSTRAP/root/usr/bin
+ln -sf ../bin $BOOTSTRAP/root/usr/sbin
+ln -sf ../lib $BOOTSTRAP/root/usr/lib
+ln -sf ../lib $BOOTSTRAP/root/usr/libexec
+ln -sf ../run/lock $BOOTSTRAP/root/var/lock
+ln -sf ../run $BOOTSTRAP/root/var/run
+
+# Prepare for the build
+ARCH=$(echo $TARGET | cut -d"-" -f1)
+export AR=llvm-ar
+export CC=clang
+export CFLAGS="-fuse-ld=lld -O3 -march=$MICROARCH -pipe --sysroot=$BOOTSTRAP/root -Wno-unused-command-line-argument"
+export CXX=clang++
+export CXXFLAGS=$CFLAGS
+export RANLIB=llvm-ranlib
+export LD=ld.lld
+export TREETAP_SYSROOT=$BOOTSTRAP/root
+export TREETAP_TARGET=$TARGET
+mkdir -p $BOOTSTRAP/build
+cd $BOOTSTRAP/build
+
+# Define the target for Maple Linux
+cat << EOF > $BOOTSTRAP/$TARGET.cmake
+set(CMAKE_ASM_COMPILER_TARGET $TARGET)
+set(CMAKE_C_COMPILER $CC)
+set(CMAKE_C_COMPILER_TARGET $TARGET)
+set(CMAKE_C_FLAGS_INIT "$CFLAGS")
+set(CMAKE_CXX_COMPILER $CXX)
+set(CMAKE_CXX_COMPILER_TARGET $TARGET)
+set(CMAKE_CXX_FLAGS_INIT "$CXXFLAGS")
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_LINKER_TYPE LLD)
+set(CMAKE_SYSROOT "$BOOTSTRAP/root")
+set(CMAKE_SYSTEM_NAME Linux)
+EOF
+
+# Install headers for Linux
+tar xf $SOURCES/linux/*/linux-*.tar*
+cd linux-*/
+# NOTE: LLVM=1 is required here because GCC and other GNU tools are required in
+# some places still. This allows us to use LLVM and bypass the parts that
+# haven't become portable yet. ~ahill
+LLVM=1 make -j $PROCS mrproper
+# NOTE: We don't use the built-in headers_install target because it requires
+# rsync for some reason. ~ahill
+LLVM=1 make -j $PROCS headers ARCH=$ARCH
+find usr/include -type f ! -name "*.h" -delete
+cp -r usr/include $BOOTSTRAP/root/usr
+cd ..
+
+# Install headers for musl
+tar xf $SOURCES/musl/*/musl-*.tar*
+cd musl-*/
+# NOTE: We are intentionally not passing --target here because musl follows the
+# GNU approach when it comes to cross-compiling. This means the build
+# script prefaces the name of every build tool with the target triple
+# we're compiling for. This is unnecessary for LLVM, because we can simply
+# pass -target <triple> to the compiler and have it generate machine code
+# for that target. ~ahill
+./configure \
+ --bindir=/bin \
+ --includedir=/usr/include \
+ --libdir=/lib \
+ --prefix=/
+make -O -j $PROCS
+make -O -j $PROCS install-headers DESTDIR=$BOOTSTRAP/root
+cd ..
+
+# Build and install compiler-rt builtins
+tar xf $SOURCES/llvm/*/llvm-project-*.tar*
+cd llvm-project-*/
+cmake -S compiler-rt/lib/builtins -B build-builtins \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX=$BOOTSTRAP/root \
+ -DCMAKE_TOOLCHAIN_FILE=$BOOTSTRAP/$TARGET.cmake \
+ -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON
+cmake --build build-builtins --parallel $PROCS
+cmake --install build-builtins --parallel $PROCS
+cd ..
+
+# Build musl for real this time
+cd musl-*/
+# TODO: CVE-2025-26519
+make clean
+# NOTE: LIBCC is required here because it will attempt to link with the build
+# system's runtime if this is not specified. ~ahill
+LIBCC="$BOOTSTRAP/root/lib/linux/libclang_rt.builtins-x86_64.a" \
+./configure \
+ --bindir=/bin \
+ --includedir=/usr/include \
+ --libdir=/lib \
+ --prefix=/
+make -O -j $PROCS
+make -O -j $PROCS install DESTDIR=$BOOTSTRAP/root
+cd ..
+
+# Include compiler-rt and musl in our environment
+export CFLAGS="$CFLAGS -Qunused-arguments -rtlib=compiler-rt -Wl,--dynamic-linker=/lib/ld-musl-$ARCH.so.1"
+export CXXFLAGS="$CXXFLAGS -Qunused-arguments -rtlib=compiler-rt -Wl,--dynamic-linker=/lib/ld-musl-$ARCH.so.1"
+
+# Build the LLVM runtimes
+# NOTE: When CMake tests the C++ compiler, it attempts to link libstdc++/libc++
+# before it even exists, causing an error. We can bypass this by simply
+# setting CMAKE_CXX_COMPILER_WORKS, therefore tricking CMake into
+# performing a successful build. Yet another instance where the genie in
+# the bottle does exactly what we asked, and not what we wanted. ~ahill
+cd llvm-project-*/
+cmake -S runtimes -B build-runtimes \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_CXX_COMPILER_WORKS=ON \
+ -DCMAKE_INSTALL_INCLUDEDIR=$BOOTSTRAP/root/usr/include \
+ -DCMAKE_INSTALL_PREFIX=$BOOTSTRAP/root \
+ -DCMAKE_TOOLCHAIN_FILE=$BOOTSTRAP/$TARGET.cmake \
+ -DCOMPILER_RT_USE_BUILTINS_LIBRARY=ON \
+ -DLIBCXX_CXX_ABI=libcxxabi \
+ -DLIBCXX_HAS_MUSL_LIBC=ON \
+ -DLIBCXX_USE_COMPILER_RT=ON \
+ -DLIBCXXABI_USE_COMPILER_RT=ON \
+ -DLIBCXXABI_USE_LLVM_UNWINDER=ON \
+ -DLIBUNWIND_USE_COMPILER_RT=ON \
+ -DLLVM_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi;libunwind"
+cmake --build build-runtimes --parallel $PROCS
+cmake --install build-runtimes --parallel $PROCS
+cd ..
+
+# Now we can introduce libc++ into the environment
+# NOTE: clang++ attempts to build with headers from the build system rather than
+# exclusively relying on the sysroot. Because of this, we must manually
+# define the proper include path. ~ahill
+export CXXFLAGS="$CXXFLAGS -isystem $BOOTSTRAP/root/usr/include/c++/v1 -nostdinc++ -stdlib=libc++"
+
+# Build LLVM itself
+# NOTE: LLVM_ENABLE_ZSTD is disabled because we don't have zstd in the sysroot,
+# and because I don't believe that a library created by Facebook should
+# be required for an operating system to function. ~ahill
+cd llvm-project-*/
+cmake -S llvm -B build-llvm \
+ -DCLANG_DEFAULT_CXX_STDLIB=libc++ \
+ -DCLANG_DEFAULT_RTLIB=compiler-rt \
+ -DCLANG_DEFAULT_UNWINDLIB=libunwind \
+ -DCLANG_VENDOR=Maple \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX=$BOOTSTRAP/root \
+ -DCMAKE_TOOLCHAIN_FILE=$BOOTSTRAP/$TARGET.cmake \
+ -DLLVM_ENABLE_LIBCXX=ON \
+ -DLLVM_ENABLE_PROJECTS="clang;lld;llvm" \
+ -DLLVM_ENABLE_ZSTD=OFF \
+ -DLLVM_HOST_TRIPLE=$TARGET
+cmake --build build-llvm --parallel $PROCS
+# ...
+cd ..