Loading debian/control +21 −6 Original line number Diff line number Diff line Loading @@ -3,12 +3,27 @@ Section: web Priority: optional Maintainer: Jan Koester <jan.koester@tuxist.de> Build-Depends: debhelper-compat (= 13), cmake (>= 3.18), libhttppp-dev, libnetplus-dev, libjson-c-dev, libparitypp-dev, libuuidplus-dev, libauthorize-dev, libconfplus-dev, libcmdplus-dev, libdbpp-dev, libbrotli-dev, libtinyxml2-dev, libsmtpclient-dev, libhtmlpp-dev, libgameinfoplus-dev, pkg-config, qt6-base-dev, qt6-declarative-dev, qt6-webengine-dev, qml6-module-qtquick-controls, qml6-module-qtquick-layouts ninja-build, libhttppp-dev <!profile.nspawn>, libnetplus-dev <!profile.nspawn>, libjson-c-dev, libparitypp-dev <!profile.nspawn>, libuuidplus-dev <!profile.nspawn>, libauthorize-dev <!profile.nspawn>, libconfplus-dev <!profile.nspawn>, libcmdplus-dev <!profile.nspawn>, libdbpp-dev <!profile.nspawn>, libbrotli-dev, libtinyxml2-dev, libsmtpclient-dev <!profile.nspawn>, libhtmlpp-dev <!profile.nspawn>, libgameinfoplus-dev <!profile.nspawn>, pkg-config, qt6-base-dev <!profile.nspawn>, qt6-declarative-dev <!profile.nspawn>, qt6-webengine-dev <!profile.nspawn>, qml6-module-qtquick-controls <!profile.nspawn>, qml6-module-qtquick-layouts <!profile.nspawn> Standards-Version: 4.6.2 Rules-Requires-Root: no Loading debian/rules +19 −0 Original line number Diff line number Diff line Loading @@ -5,12 +5,31 @@ export DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) %: dh $@ --buildsystem=cmake TOOLCHAIN_FILE = /usr/local/musl/share/musl-llvm-toolchain.cmake IS_NSPAWN = $(filter nspawn,$(DEB_BUILD_PROFILES)) override_dh_auto_configure: ifneq ($(IS_NSPAWN),) dh_auto_configure -- \ -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE) \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_LIBDIR=lib/$(DEB_HOST_MULTIARCH) \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_EDITOR=OFF else dh_auto_configure -- \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_LIBDIR=lib/$(DEB_HOST_MULTIARCH) \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_EDITOR=ON endif override_dh_shlibdeps: ifneq ($(IS_NSPAWN),) dh_shlibdeps -- --ignore-missing-info else dh_shlibdeps endif override_dh_install: dh_install Loading packaging/build-nspawn.sh 0 → 100755 +325 −0 Original line number Diff line number Diff line #!/bin/bash # # build-nspawn.sh — Build blogi .deb package using systemd-nspawn # with a musl/LLVM/libc++/compiler-rt toolchain in a chroot. # # Usage: ./packaging/build-nspawn.sh [--clean] [--arch amd64] # # Requires: systemd-container, debootstrap, wget # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" # Configuration ARCH="${ARCH:-amd64}" CHROOT_BASE="/var/lib/blogi-buildroot" CHROOT_DIR="$CHROOT_BASE/rootfs" BUILD_DIR="/build" OUTPUT_DIR="$PROJECT_DIR/packaging/output" MUSL_VERSION="1.2.5" LLVM_VERSION="18" # Git repositories for custom libraries GIT_BASE="https://git.tuxist.de/git" declare -A LIBS=( [libcmdplus]="$GIT_BASE/jan.koester/libcmdplus.git" [uuidplus]="$GIT_BASE/tuxist/uuidplus.git" [libnetplus]="$GIT_BASE/jan.koester/libnetplus.git" [libhtmlpp]="$GIT_BASE/jan.koester/libhtmlpp.git" [libhttppp]="$GIT_BASE/jan.koester/libhttppp.git" [libconfplus]="$GIT_BASE/jan.koester/libconfplus.git" [libdbpp]="$GIT_BASE/jan.koester/libdbpp.git" [libgameinfoplus]="$GIT_BASE/jan.koester/libgameinfoplus.git" [libparitypp]="$GIT_BASE/tuxist/libparitypp.git" [authdb]="$GIT_BASE/tuxist/authdb.git" [mediadb]="$GIT_BASE/tuxist/mediadb.git" [smtpclient]="https://github.com/Tuxist/CPP-SMTPClient-library.git" ) # Build order (dependency-sorted) LIB_ORDER=( libcmdplus uuidplus libnetplus libhtmlpp libhttppp libconfplus libdbpp libgameinfoplus libparitypp authdb mediadb smtpclient ) # Parse arguments CLEAN=0 while [[ $# -gt 0 ]]; do case "$1" in --clean) CLEAN=1; shift ;; --arch) ARCH="$2"; shift 2 ;; *) echo "Unknown option: $1"; exit 1 ;; esac done if [[ $EUID -ne 0 ]]; then echo "This script must be run as root (for nspawn)." echo "Usage: sudo $0 [--clean]" exit 1 fi # ───────────────────────────────────────────────────────────── # Phase 1: Create minimal Debian chroot # ───────────────────────────────────────────────────────────── setup_chroot() { if [[ $CLEAN -eq 1 ]] && [[ -d "$CHROOT_DIR" ]]; then echo "==> Cleaning existing chroot..." rm -rf "$CHROOT_DIR" fi if [[ -d "$CHROOT_DIR/usr/bin" ]]; then echo "==> Chroot already exists, skipping bootstrap" return fi echo "==> Creating Debian chroot at $CHROOT_DIR ..." mkdir -p "$CHROOT_DIR" debootstrap --variant=minbase --arch="$ARCH" bookworm "$CHROOT_DIR" http://deb.debian.org/debian # Install minimal build dependencies in the chroot systemd-nspawn -D "$CHROOT_DIR" --pipe -- bash -c ' apt-get update apt-get install -y --no-install-recommends \ ca-certificates wget git cmake ninja-build pkg-config \ libyaml-dev libjson-c-dev libbrotli-dev libtinyxml2-dev \ libsqlite3-dev libpq-dev uuid-dev \ xz-utils python3 file dpkg-dev fakeroot debhelper \ libffmpeg-nvenc-dev ffmpeg ' } # ───────────────────────────────────────────────────────────── # Phase 2: Install LLVM toolchain + musl + libc++ + compiler-rt # ───────────────────────────────────────────────────────────── setup_toolchain() { if [[ -f "$CHROOT_DIR/usr/local/musl/bin/musl-clang" ]]; then echo "==> Toolchain already set up, skipping" return fi echo "==> Setting up LLVM ${LLVM_VERSION} + musl + libc++ toolchain..." systemd-nspawn -D "$CHROOT_DIR" --pipe -- bash -c " set -e # Install LLVM/Clang apt-get install -y --no-install-recommends \ clang-${LLVM_VERSION} lld-${LLVM_VERSION} \ llvm-${LLVM_VERSION}-dev \ libc++-${LLVM_VERSION}-dev libc++abi-${LLVM_VERSION}-dev \ libunwind-${LLVM_VERSION}-dev \ compiler-rt-${LLVM_VERSION} # Set up symlinks update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${LLVM_VERSION} 100 update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${LLVM_VERSION} 100 update-alternatives --install /usr/bin/lld lld /usr/bin/lld-${LLVM_VERSION} 100 update-alternatives --install /usr/bin/ld.lld ld.lld /usr/bin/ld.lld-${LLVM_VERSION} 100 ln -sf /usr/bin/clang-${LLVM_VERSION} /usr/bin/cc ln -sf /usr/bin/clang++-${LLVM_VERSION} /usr/bin/c++ # Build musl from source cd /tmp wget -q https://musl.libc.org/releases/musl-${MUSL_VERSION}.tar.gz tar xf musl-${MUSL_VERSION}.tar.gz cd musl-${MUSL_VERSION} CC=clang-${LLVM_VERSION} ./configure --prefix=/usr/local/musl --syslibdir=/usr/local/musl/lib make -j\$(nproc) make install # Create musl-clang wrapper that uses libc++ and compiler-rt cat > /usr/local/musl/bin/musl-clang++ << 'WRAPPER' #!/bin/sh exec clang++ \ --target=x86_64-linux-musl \ --sysroot=/usr/local/musl \ -isystem /usr/local/musl/include \ -isystem /usr/include/c++/v1 \ -nostdinc++ \ -stdlib=libc++ \ -rtlib=compiler-rt \ -fuse-ld=lld \ -L/usr/local/musl/lib \ -L/usr/lib/llvm-${LLVM_VERSION}/lib \ -lc++abi \ -lunwind \ -static \ \"\$@\" WRAPPER chmod +x /usr/local/musl/bin/musl-clang++ cat > /usr/local/musl/bin/musl-clang << 'WRAPPER' #!/bin/sh exec clang \ --target=x86_64-linux-musl \ --sysroot=/usr/local/musl \ -isystem /usr/local/musl/include \ -rtlib=compiler-rt \ -fuse-ld=lld \ -L/usr/local/musl/lib \ -static \ \"\$@\" WRAPPER chmod +x /usr/local/musl/bin/musl-clang # Create CMake toolchain file mkdir -p /usr/local/musl/share cat > /usr/local/musl/share/musl-llvm-toolchain.cmake << 'CMAKE' set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR x86_64) set(CMAKE_C_COMPILER /usr/local/musl/bin/musl-clang) set(CMAKE_CXX_COMPILER /usr/local/musl/bin/musl-clang++) set(CMAKE_C_FLAGS_INIT \"-fPIC\") set(CMAKE_CXX_FLAGS_INIT \"-fPIC -stdlib=libc++\") set(CMAKE_EXE_LINKER_FLAGS_INIT \"-static -stdlib=libc++ -lc++abi -lunwind -rtlib=compiler-rt -fuse-ld=lld\") set(CMAKE_SHARED_LINKER_FLAGS_INIT \"-stdlib=libc++ -lc++abi -lunwind -rtlib=compiler-rt -fuse-ld=lld\") set(CMAKE_FIND_ROOT_PATH /usr/local/musl /usr/local) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) CMAKE echo '==> Toolchain setup complete' " } # ───────────────────────────────────────────────────────────── # Phase 3: Build all dependency libraries # ───────────────────────────────────────────────────────────── build_libraries() { echo "==> Building dependency libraries inside nspawn..." # Bind-mount nothing yet, clone inside systemd-nspawn -D "$CHROOT_DIR" --pipe -- bash -c " set -e TOOLCHAIN=/usr/local/musl/share/musl-llvm-toolchain.cmake PREFIX=/usr/local mkdir -p /build/libs && cd /build/libs build_lib() { local name=\$1 local url=\$2 local extra_args=\${3:-} if [ -f /build/libs/.\${name}.done ]; then echo \" [skip] \$name already built\" return fi echo \" [build] \$name\" if [ ! -d \$name ]; then git clone --depth 1 \$url \$name fi mkdir -p \$name/build && cd \$name/build cmake .. -G Ninja \ -DCMAKE_TOOLCHAIN_FILE=\$TOOLCHAIN \ -DCMAKE_INSTALL_PREFIX=\$PREFIX \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ \$extra_args ninja ninja install cd /build/libs touch .\${name}.done } build_lib libcmdplus '${LIBS[libcmdplus]}' build_lib uuidplus '${LIBS[uuidplus]}' build_lib libnetplus '${LIBS[libnetplus]}' build_lib libhtmlpp '${LIBS[libhtmlpp]}' build_lib libhttppp '${LIBS[libhttppp]}' build_lib libconfplus '${LIBS[libconfplus]}' build_lib libdbpp '${LIBS[libdbpp]}' build_lib libgameinfoplus '${LIBS[libgameinfoplus]}' build_lib libparitypp '${LIBS[libparitypp]}' build_lib authdb '${LIBS[authdb]}' '-DBUILD_BINDINGS=OFF' build_lib mediadb '${LIBS[mediadb]}' build_lib smtpclient '${LIBS[smtpclient]}' '-DCMAKE_INSTALL_LIBDIR=/usr/local/lib -DCMAKE_INSTALL_INCLUDEDIR=/usr/local/include' echo '==> All libraries built successfully' " } # ───────────────────────────────────────────────────────────── # Phase 4: Build blogi and create .deb # ───────────────────────────────────────────────────────────── build_blogi() { echo "==> Building blogi package..." # Bind-mount the source tree read-only systemd-nspawn -D "$CHROOT_DIR" \ --bind-ro="$PROJECT_DIR:$BUILD_DIR/blogi-src" \ --pipe -- bash -c " set -e TOOLCHAIN=/usr/local/musl/share/musl-llvm-toolchain.cmake # Copy source (we don't modify the bind mount) rm -rf $BUILD_DIR/blogi cp -a $BUILD_DIR/blogi-src $BUILD_DIR/blogi cd $BUILD_DIR/blogi # Build mkdir -p build && cd build cmake .. -G Ninja \ -DCMAKE_TOOLCHAIN_FILE=\$TOOLCHAIN \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_LIBDIR=lib/x86_64-linux-gnu \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_EDITOR=OFF ninja # Package via dpkg-buildpackage cd $BUILD_DIR/blogi dpkg-buildpackage -us -uc -b --build-profiles=nspawn # Collect .deb files mkdir -p $BUILD_DIR/output mv ../*.deb $BUILD_DIR/output/ 2>/dev/null || true mv ../*.changes $BUILD_DIR/output/ 2>/dev/null || true mv ../*.buildinfo $BUILD_DIR/output/ 2>/dev/null || true echo '==> Package build complete' ls -la $BUILD_DIR/output/ " # Copy output to host mkdir -p "$OUTPUT_DIR" cp "$CHROOT_DIR/$BUILD_DIR/output/"*.deb "$OUTPUT_DIR/" 2>/dev/null || true cp "$CHROOT_DIR/$BUILD_DIR/output/"*.changes "$OUTPUT_DIR/" 2>/dev/null || true cp "$CHROOT_DIR/$BUILD_DIR/output/"*.buildinfo "$OUTPUT_DIR/" 2>/dev/null || true echo "==> Packages available in: $OUTPUT_DIR" ls -la "$OUTPUT_DIR/" } # ───────────────────────────────────────────────────────────── # Main # ───────────────────────────────────────────────────────────── echo "╔══════════════════════════════════════════════════════════╗" echo "║ blogi nspawn build — musl + LLVM libc++ + compiler-rt ║" echo "╚══════════════════════════════════════════════════════════╝" echo "" setup_chroot setup_toolchain build_libraries build_blogi echo "" echo "==> Done. Packages in $OUTPUT_DIR" Loading
debian/control +21 −6 Original line number Diff line number Diff line Loading @@ -3,12 +3,27 @@ Section: web Priority: optional Maintainer: Jan Koester <jan.koester@tuxist.de> Build-Depends: debhelper-compat (= 13), cmake (>= 3.18), libhttppp-dev, libnetplus-dev, libjson-c-dev, libparitypp-dev, libuuidplus-dev, libauthorize-dev, libconfplus-dev, libcmdplus-dev, libdbpp-dev, libbrotli-dev, libtinyxml2-dev, libsmtpclient-dev, libhtmlpp-dev, libgameinfoplus-dev, pkg-config, qt6-base-dev, qt6-declarative-dev, qt6-webengine-dev, qml6-module-qtquick-controls, qml6-module-qtquick-layouts ninja-build, libhttppp-dev <!profile.nspawn>, libnetplus-dev <!profile.nspawn>, libjson-c-dev, libparitypp-dev <!profile.nspawn>, libuuidplus-dev <!profile.nspawn>, libauthorize-dev <!profile.nspawn>, libconfplus-dev <!profile.nspawn>, libcmdplus-dev <!profile.nspawn>, libdbpp-dev <!profile.nspawn>, libbrotli-dev, libtinyxml2-dev, libsmtpclient-dev <!profile.nspawn>, libhtmlpp-dev <!profile.nspawn>, libgameinfoplus-dev <!profile.nspawn>, pkg-config, qt6-base-dev <!profile.nspawn>, qt6-declarative-dev <!profile.nspawn>, qt6-webengine-dev <!profile.nspawn>, qml6-module-qtquick-controls <!profile.nspawn>, qml6-module-qtquick-layouts <!profile.nspawn> Standards-Version: 4.6.2 Rules-Requires-Root: no Loading
debian/rules +19 −0 Original line number Diff line number Diff line Loading @@ -5,12 +5,31 @@ export DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) %: dh $@ --buildsystem=cmake TOOLCHAIN_FILE = /usr/local/musl/share/musl-llvm-toolchain.cmake IS_NSPAWN = $(filter nspawn,$(DEB_BUILD_PROFILES)) override_dh_auto_configure: ifneq ($(IS_NSPAWN),) dh_auto_configure -- \ -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE) \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_LIBDIR=lib/$(DEB_HOST_MULTIARCH) \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_EDITOR=OFF else dh_auto_configure -- \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_LIBDIR=lib/$(DEB_HOST_MULTIARCH) \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_EDITOR=ON endif override_dh_shlibdeps: ifneq ($(IS_NSPAWN),) dh_shlibdeps -- --ignore-missing-info else dh_shlibdeps endif override_dh_install: dh_install Loading
packaging/build-nspawn.sh 0 → 100755 +325 −0 Original line number Diff line number Diff line #!/bin/bash # # build-nspawn.sh — Build blogi .deb package using systemd-nspawn # with a musl/LLVM/libc++/compiler-rt toolchain in a chroot. # # Usage: ./packaging/build-nspawn.sh [--clean] [--arch amd64] # # Requires: systemd-container, debootstrap, wget # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" # Configuration ARCH="${ARCH:-amd64}" CHROOT_BASE="/var/lib/blogi-buildroot" CHROOT_DIR="$CHROOT_BASE/rootfs" BUILD_DIR="/build" OUTPUT_DIR="$PROJECT_DIR/packaging/output" MUSL_VERSION="1.2.5" LLVM_VERSION="18" # Git repositories for custom libraries GIT_BASE="https://git.tuxist.de/git" declare -A LIBS=( [libcmdplus]="$GIT_BASE/jan.koester/libcmdplus.git" [uuidplus]="$GIT_BASE/tuxist/uuidplus.git" [libnetplus]="$GIT_BASE/jan.koester/libnetplus.git" [libhtmlpp]="$GIT_BASE/jan.koester/libhtmlpp.git" [libhttppp]="$GIT_BASE/jan.koester/libhttppp.git" [libconfplus]="$GIT_BASE/jan.koester/libconfplus.git" [libdbpp]="$GIT_BASE/jan.koester/libdbpp.git" [libgameinfoplus]="$GIT_BASE/jan.koester/libgameinfoplus.git" [libparitypp]="$GIT_BASE/tuxist/libparitypp.git" [authdb]="$GIT_BASE/tuxist/authdb.git" [mediadb]="$GIT_BASE/tuxist/mediadb.git" [smtpclient]="https://github.com/Tuxist/CPP-SMTPClient-library.git" ) # Build order (dependency-sorted) LIB_ORDER=( libcmdplus uuidplus libnetplus libhtmlpp libhttppp libconfplus libdbpp libgameinfoplus libparitypp authdb mediadb smtpclient ) # Parse arguments CLEAN=0 while [[ $# -gt 0 ]]; do case "$1" in --clean) CLEAN=1; shift ;; --arch) ARCH="$2"; shift 2 ;; *) echo "Unknown option: $1"; exit 1 ;; esac done if [[ $EUID -ne 0 ]]; then echo "This script must be run as root (for nspawn)." echo "Usage: sudo $0 [--clean]" exit 1 fi # ───────────────────────────────────────────────────────────── # Phase 1: Create minimal Debian chroot # ───────────────────────────────────────────────────────────── setup_chroot() { if [[ $CLEAN -eq 1 ]] && [[ -d "$CHROOT_DIR" ]]; then echo "==> Cleaning existing chroot..." rm -rf "$CHROOT_DIR" fi if [[ -d "$CHROOT_DIR/usr/bin" ]]; then echo "==> Chroot already exists, skipping bootstrap" return fi echo "==> Creating Debian chroot at $CHROOT_DIR ..." mkdir -p "$CHROOT_DIR" debootstrap --variant=minbase --arch="$ARCH" bookworm "$CHROOT_DIR" http://deb.debian.org/debian # Install minimal build dependencies in the chroot systemd-nspawn -D "$CHROOT_DIR" --pipe -- bash -c ' apt-get update apt-get install -y --no-install-recommends \ ca-certificates wget git cmake ninja-build pkg-config \ libyaml-dev libjson-c-dev libbrotli-dev libtinyxml2-dev \ libsqlite3-dev libpq-dev uuid-dev \ xz-utils python3 file dpkg-dev fakeroot debhelper \ libffmpeg-nvenc-dev ffmpeg ' } # ───────────────────────────────────────────────────────────── # Phase 2: Install LLVM toolchain + musl + libc++ + compiler-rt # ───────────────────────────────────────────────────────────── setup_toolchain() { if [[ -f "$CHROOT_DIR/usr/local/musl/bin/musl-clang" ]]; then echo "==> Toolchain already set up, skipping" return fi echo "==> Setting up LLVM ${LLVM_VERSION} + musl + libc++ toolchain..." systemd-nspawn -D "$CHROOT_DIR" --pipe -- bash -c " set -e # Install LLVM/Clang apt-get install -y --no-install-recommends \ clang-${LLVM_VERSION} lld-${LLVM_VERSION} \ llvm-${LLVM_VERSION}-dev \ libc++-${LLVM_VERSION}-dev libc++abi-${LLVM_VERSION}-dev \ libunwind-${LLVM_VERSION}-dev \ compiler-rt-${LLVM_VERSION} # Set up symlinks update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${LLVM_VERSION} 100 update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${LLVM_VERSION} 100 update-alternatives --install /usr/bin/lld lld /usr/bin/lld-${LLVM_VERSION} 100 update-alternatives --install /usr/bin/ld.lld ld.lld /usr/bin/ld.lld-${LLVM_VERSION} 100 ln -sf /usr/bin/clang-${LLVM_VERSION} /usr/bin/cc ln -sf /usr/bin/clang++-${LLVM_VERSION} /usr/bin/c++ # Build musl from source cd /tmp wget -q https://musl.libc.org/releases/musl-${MUSL_VERSION}.tar.gz tar xf musl-${MUSL_VERSION}.tar.gz cd musl-${MUSL_VERSION} CC=clang-${LLVM_VERSION} ./configure --prefix=/usr/local/musl --syslibdir=/usr/local/musl/lib make -j\$(nproc) make install # Create musl-clang wrapper that uses libc++ and compiler-rt cat > /usr/local/musl/bin/musl-clang++ << 'WRAPPER' #!/bin/sh exec clang++ \ --target=x86_64-linux-musl \ --sysroot=/usr/local/musl \ -isystem /usr/local/musl/include \ -isystem /usr/include/c++/v1 \ -nostdinc++ \ -stdlib=libc++ \ -rtlib=compiler-rt \ -fuse-ld=lld \ -L/usr/local/musl/lib \ -L/usr/lib/llvm-${LLVM_VERSION}/lib \ -lc++abi \ -lunwind \ -static \ \"\$@\" WRAPPER chmod +x /usr/local/musl/bin/musl-clang++ cat > /usr/local/musl/bin/musl-clang << 'WRAPPER' #!/bin/sh exec clang \ --target=x86_64-linux-musl \ --sysroot=/usr/local/musl \ -isystem /usr/local/musl/include \ -rtlib=compiler-rt \ -fuse-ld=lld \ -L/usr/local/musl/lib \ -static \ \"\$@\" WRAPPER chmod +x /usr/local/musl/bin/musl-clang # Create CMake toolchain file mkdir -p /usr/local/musl/share cat > /usr/local/musl/share/musl-llvm-toolchain.cmake << 'CMAKE' set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR x86_64) set(CMAKE_C_COMPILER /usr/local/musl/bin/musl-clang) set(CMAKE_CXX_COMPILER /usr/local/musl/bin/musl-clang++) set(CMAKE_C_FLAGS_INIT \"-fPIC\") set(CMAKE_CXX_FLAGS_INIT \"-fPIC -stdlib=libc++\") set(CMAKE_EXE_LINKER_FLAGS_INIT \"-static -stdlib=libc++ -lc++abi -lunwind -rtlib=compiler-rt -fuse-ld=lld\") set(CMAKE_SHARED_LINKER_FLAGS_INIT \"-stdlib=libc++ -lc++abi -lunwind -rtlib=compiler-rt -fuse-ld=lld\") set(CMAKE_FIND_ROOT_PATH /usr/local/musl /usr/local) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) CMAKE echo '==> Toolchain setup complete' " } # ───────────────────────────────────────────────────────────── # Phase 3: Build all dependency libraries # ───────────────────────────────────────────────────────────── build_libraries() { echo "==> Building dependency libraries inside nspawn..." # Bind-mount nothing yet, clone inside systemd-nspawn -D "$CHROOT_DIR" --pipe -- bash -c " set -e TOOLCHAIN=/usr/local/musl/share/musl-llvm-toolchain.cmake PREFIX=/usr/local mkdir -p /build/libs && cd /build/libs build_lib() { local name=\$1 local url=\$2 local extra_args=\${3:-} if [ -f /build/libs/.\${name}.done ]; then echo \" [skip] \$name already built\" return fi echo \" [build] \$name\" if [ ! -d \$name ]; then git clone --depth 1 \$url \$name fi mkdir -p \$name/build && cd \$name/build cmake .. -G Ninja \ -DCMAKE_TOOLCHAIN_FILE=\$TOOLCHAIN \ -DCMAKE_INSTALL_PREFIX=\$PREFIX \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ \$extra_args ninja ninja install cd /build/libs touch .\${name}.done } build_lib libcmdplus '${LIBS[libcmdplus]}' build_lib uuidplus '${LIBS[uuidplus]}' build_lib libnetplus '${LIBS[libnetplus]}' build_lib libhtmlpp '${LIBS[libhtmlpp]}' build_lib libhttppp '${LIBS[libhttppp]}' build_lib libconfplus '${LIBS[libconfplus]}' build_lib libdbpp '${LIBS[libdbpp]}' build_lib libgameinfoplus '${LIBS[libgameinfoplus]}' build_lib libparitypp '${LIBS[libparitypp]}' build_lib authdb '${LIBS[authdb]}' '-DBUILD_BINDINGS=OFF' build_lib mediadb '${LIBS[mediadb]}' build_lib smtpclient '${LIBS[smtpclient]}' '-DCMAKE_INSTALL_LIBDIR=/usr/local/lib -DCMAKE_INSTALL_INCLUDEDIR=/usr/local/include' echo '==> All libraries built successfully' " } # ───────────────────────────────────────────────────────────── # Phase 4: Build blogi and create .deb # ───────────────────────────────────────────────────────────── build_blogi() { echo "==> Building blogi package..." # Bind-mount the source tree read-only systemd-nspawn -D "$CHROOT_DIR" \ --bind-ro="$PROJECT_DIR:$BUILD_DIR/blogi-src" \ --pipe -- bash -c " set -e TOOLCHAIN=/usr/local/musl/share/musl-llvm-toolchain.cmake # Copy source (we don't modify the bind mount) rm -rf $BUILD_DIR/blogi cp -a $BUILD_DIR/blogi-src $BUILD_DIR/blogi cd $BUILD_DIR/blogi # Build mkdir -p build && cd build cmake .. -G Ninja \ -DCMAKE_TOOLCHAIN_FILE=\$TOOLCHAIN \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_LIBDIR=lib/x86_64-linux-gnu \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_EDITOR=OFF ninja # Package via dpkg-buildpackage cd $BUILD_DIR/blogi dpkg-buildpackage -us -uc -b --build-profiles=nspawn # Collect .deb files mkdir -p $BUILD_DIR/output mv ../*.deb $BUILD_DIR/output/ 2>/dev/null || true mv ../*.changes $BUILD_DIR/output/ 2>/dev/null || true mv ../*.buildinfo $BUILD_DIR/output/ 2>/dev/null || true echo '==> Package build complete' ls -la $BUILD_DIR/output/ " # Copy output to host mkdir -p "$OUTPUT_DIR" cp "$CHROOT_DIR/$BUILD_DIR/output/"*.deb "$OUTPUT_DIR/" 2>/dev/null || true cp "$CHROOT_DIR/$BUILD_DIR/output/"*.changes "$OUTPUT_DIR/" 2>/dev/null || true cp "$CHROOT_DIR/$BUILD_DIR/output/"*.buildinfo "$OUTPUT_DIR/" 2>/dev/null || true echo "==> Packages available in: $OUTPUT_DIR" ls -la "$OUTPUT_DIR/" } # ───────────────────────────────────────────────────────────── # Main # ───────────────────────────────────────────────────────────── echo "╔══════════════════════════════════════════════════════════╗" echo "║ blogi nspawn build — musl + LLVM libc++ + compiler-rt ║" echo "╚══════════════════════════════════════════════════════════╝" echo "" setup_chroot setup_toolchain build_libraries build_blogi echo "" echo "==> Done. Packages in $OUTPUT_DIR"