#!/bin/bash # ============================================================================= # build-pagan-rootfs.sh - Minimalny rootfs LFS + PAG/PAGBUILD (ROOTFS ONLY) # ============================================================================= # Buduje minimalne środowisko LFS (Ch. 5 + 6) z pag i pagbuild do budowania # pakietów. Bez BLFS, bez kernela, bez DE, bez IMG/ISO. # ============================================================================= set -euo pipefail # ========================= KONFIGURACJA ========================= # Absolutna ścieżka do katalogu skryptów – działa nawet po `cd /` w main() SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PAGAN_ROOT="${PAGAN_ROOT:-/mnt/pagan-rootfs}" PAGAN_VERSION="${PAGAN_VERSION:-0.0.1}" BUILD_PROFILE="rootfs" PAGAN_RELEASE="2026.07" LFS_VERSION="13.0" # Kernel KERNEL_VERSION="${KERNEL_VERSION:-6.19.14}" KERNEL_URL="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${KERNEL_VERSION}.tar.xz" # Hardware MAKEFLAGS="-j$(nproc)" LFS_TGT="$(uname -m)-pagan-linux-gnu" # Ścieżki SRC_DIR="$PAGAN_ROOT/sources" TOOLS_DIR="$PAGAN_ROOT/tools" CROSS_BIN="$TOOLS_DIR/bin" OUTPUT_DIR="${OUTPUT_DIR:-/var/pagan-rootfs/output}" mkdir -p "$OUTPUT_DIR" # Wymuś pełne czyszczenie i budowę od zera: 1|true|yes REBUILD_FROM_SCRATCH="${REBUILD_FROM_SCRATCH:-0}" # ========================= SYSTEM LOGÓW ========================= : "${PAGAN_LOG_LEVEL:=0}" LOG_FILE="/var/log/pagan-rootfs.log" SUMMARY_FILE="/var/log/pagan-rootfs.summary.log" mkdir -p "$(dirname "$LOG_FILE")" cat > "$LOG_FILE" < "$SUMMARY_FILE" # ========================= KOLORY ========================= RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' BLUE='\033[0;34m'; MAGENTA='\033[0;35m'; CYAN='\033[0;36m' BOLD='\033[1m'; DIM='\033[2m'; NC='\033[0m' # ========================= INTERFEJS UŻYTKOWNIKA ========================= source "$SCRIPT_DIR/ui.sh" ui_init # ========================= STATYSTYKI ========================= PKG_BUILT=0; PKG_FAILED=0; PKG_SKIPPED=0 RESUME_FILE="${RESUME_FILE:-/var/log/pagan-rootfs-build.done}" _is_built() { local pkg="$1" [[ -f "$RESUME_FILE" ]] && grep -qxF "$pkg" "$RESUME_FILE" 2>/dev/null } _mark_built() { local pkg="$1" mkdir -p "$(dirname "$RESUME_FILE")" echo "$pkg" >> "$RESUME_FILE" } _is_true() { case "${1:-}" in 1|true|TRUE|yes|YES|on|ON|y|Y) return 0 ;; *) return 1 ;; esac } clean_build_state() { step "Tryb: zbuduj od nowa" if [[ -z "$PAGAN_ROOT" || "$PAGAN_ROOT" == "/" ]]; then error "Niebezpieczny PAGAN_ROOT='$PAGAN_ROOT' - odmawiam czyszczenia" fi if declare -F umount_virtual_fs >/dev/null; then umount_virtual_fs >/dev/null 2>&1 || true fi warn "Czyszczenie katalogu builda: $PAGAN_ROOT" rm -rf --one-file-system "$PAGAN_ROOT" rm -f "$RESUME_FILE" mkdir -p "$PAGAN_ROOT" "$OUTPUT_DIR" ok "Wyczyszczono rootfs i stan resume; start od zera" } # ========================= FUNKCJE LOGOWANIA ========================= _log_raw() { local color="$1" lvl="$2" msg="$3" local ts; ts=$(date '+%H:%M:%S') echo -e "${color}[${ts}] [${lvl}]${NC} $msg" echo "[${ts}] [${lvl}] $msg" >> "$LOG_FILE" } dbg() { [[ $PAGAN_LOG_LEVEL -le 0 ]] && _log_raw "${DIM}" "DEBUG" "$*" || true; } info() { [[ $PAGAN_LOG_LEVEL -le 1 ]] && _log_raw "${BLUE}" "INFO " "$*" || true; } warn() { [[ $PAGAN_LOG_LEVEL -le 2 ]] && _log_raw "${YELLOW}" "WARN " "$*" >&2 || true; } error() { _log_raw "${RED}" "ERROR" "$*" >&2 _dump_stack _log_raw "${RED}" "FATAL" "Budowa przerwana. Log: $LOG_FILE" >&2 exit 1 } ok() { _log_raw "${GREEN}" "OK " "$*" ((PKG_BUILT++)) || true echo "✓ $*" >> "$SUMMARY_FILE" } step() { local title="$*" echo "" echo -e "${MAGENTA}${BOLD}═══ ${title} ═══${NC}" echo "━━━ $(date '+%H:%M:%S') ━━━ ${title} ━━━" >> "$LOG_FILE" dbg "START: $title" } _dump_stack() { local frame=0 echo " Stack trace:" >> "$LOG_FILE" while caller $frame 2>/dev/null; do ((frame++)) done >> "$LOG_FILE" } _on_error() { local lineno="$1" cmd="$2" echo -e "${RED}[ERROR]${NC} Linia ${lineno}: \"${cmd}\"" | tee -a "$LOG_FILE" >&2 echo "[$(date '+%H:%M:%S')] [ERROR] Linia ${lineno}: ${cmd}" >> "$LOG_FILE" _dump_stack } trap '_on_error "${LINENO}" "${BASH_COMMAND}"' ERR _show_summary() { # Best-effort cleanup: avoid stale mounts after cancel/error. if declare -F umount_virtual_fs >/dev/null; then umount_virtual_fs >/dev/null 2>&1 || true fi ui_summary } trap _show_summary EXIT # ========================= BANNER ========================= show_banner() { cat << 'EOF' ╔═══════════════════════════════════════════════════════════════════╗ ║ ║ ║ ██████ █████ █████ █████ ███ ██ ║ ║ ██ ██ ██ ██ ██ ██ ██ ████ ██ ║ ║ ██████ ███████ ██████ ███████ ██ ██ ██ ║ ║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ║ ║ ██ ██ ██ █████ ██ ██ ██ ████ ║ ║ ║ ║ ╔══════════════════════════════════════════════════════════╗ ║ EOF # Wiersze ze zmiennymi – padding liczony w locie, żeby ramka # zawsze się domykała (niezależnie od długości wersji/architektury). local pad entry for entry in \ " Pagan Linux Builder v${PAGAN_VERSION}" \ " LFS ${LFS_VERSION} + PAG/PAGBUILD (rootfs only)" \ " Architektura: $(uname -m)" \ " Data: $(date +'%Y-%m-%d %H:%M:%S')"; do pad=$(printf '%*s' "$((58 - ${#entry}))" "") printf '║ ║%s%s║ ║\n' "$entry" "$pad" done cat << 'EOF' ║ ╚══════════════════════════════════════════════════════════╝ ║ ║ ║ ╚═══════════════════════════════════════════════════════════════════╝ EOF } # ========================= SPRAWDZANIE ZALEŻNOŚCI HOST ========================= check_dependencies() { step "Sprawdzanie zależności systemowych hosta" local deps=( "gcc" "g++" "make" "bison" "flex" "texinfo" "wget" "curl" "tar" "xz" "bzip2" "gzip" "patch" "gawk" "sed" "grep" "find" "file" "diff" "cmp" "python3" "perl" "m4" "cmake" "git" "rsync" "cpio" "gpg" "pkg-config" "xorriso" "mkfs.fat" "parted" "mksquashfs" "ninja" "meson" ) local missing=() for dep in "${deps[@]}"; do if ! command -v "$dep" &>/dev/null; then missing+=("$dep") fi done if [[ ${#missing[@]} -gt 0 ]]; then warn "Brakujące pakiety na hoście: ${missing[*]}" info "Instalowanie brakujących pakietów..." if command -v apt-get &>/dev/null; then apt-get update && apt-get install -y "${missing[@]}" \ libncurses-dev libssl-dev libreadline-dev libxml2-dev libxslt1-dev \ libxml-parser-perl libglib2.0-dev libgtk-3-dev libgtk-3-dev \ libpango1.0-dev libcairo2-dev libgdk-pixbuf-2.0-dev \ libdbus-1-dev libsystemd-dev libudev-dev libmnl-dev libevdev-dev \ libacl1-dev libattr1-dev libpam0g-dev libgirepository1.0-dev \ gobject-introspection libqt5svg5-dev qtbase5-dev qtdeclarative5-dev \ qttools5-dev shared-mime-info intltool xsltproc gperf valac \ gcc-multilib libc6-dev-i386 python3-pip python3-yaml elif command -v dnf &>/dev/null; then dnf install -y "${missing[@]}" python3-pip python3-pyyaml elif command -v pacman &>/dev/null; then pacman -Sy --noconfirm --needed base-devel python-pip python-yaml "${missing[@]}" else error "Nieznany menedżer pakietów hosta. Zainstaluj ręcznie: ${missing[*]}" fi fi ok "Wszystkie zależności hosta spełnione" } # ========================= LFS PATCH CHECK (BEST-EFFORT) ========================= check_lfs_patches() { step "Sprawdzanie dostępnych patchy LFS (best-effort)" local patch_index_url="https://www.linuxfromscratch.org/patches/lfs/${LFS_VERSION}/" local html if ! html=$(curl -fsSL --max-time 20 "$patch_index_url" 2>/dev/null); then warn "Nie udało się pobrać indeksu patchy LFS: $patch_index_url" warn "Pomijam check patchy (build będzie kontynuowany)." return 0 fi local tracked=( "bash-5.2.37" "bzip2-1.0.8" "coreutils-9.5" "diffutils-3.10" "findutils-4.10.0" "glibc-2.44" "grep-3.11" "gzip-1.13" "make-4.4.1" "openssl-3.3.2" "python-3.12.5" "sed-4.9" "systemd-256.4" "tar-1.35" "util-linux-2.40.2" ) local found=0 for pkg in "${tracked[@]}"; do if echo "$html" | rg -qi "${pkg}.*\.patch"; then warn "LFS patch dostępny dla: $pkg" ((found++)) || true fi done if [[ $found -eq 0 ]]; then ok "Nie wykryto oczywistych patchy dla śledzonych pakietów LFS ${LFS_VERSION}" else warn "Wykryto $found potencjalnych patchy LFS. Rozważ integrację przed release build." fi } # ========================= INICJALIZACJA STRUKTURY ========================= init_build() { step "Inicjalizacja środowiska budowy PaganOS" cd / mkdir -p "$PAGAN_ROOT" "$SRC_DIR" "$TOOLS_DIR" "$OUTPUT_DIR" # Współdzielone źródła z głównego buildera (unikaj ponownego pobierania) local MAIN_SRC="/mnt/pagan/sources" if [[ -d "$MAIN_SRC" ]] && [[ "$SRC_DIR" != "$MAIN_SRC" ]]; then info "↻ Współdzielę źródła z $MAIN_SRC" rm -rf "$SRC_DIR" ln -sf "$MAIN_SRC" "$SRC_DIR" fi # Katalogi systemowe POSIX for dir in usr bin sbin lib lib64 etc var boot home root \ opt tmp run mnt media srv; do mkdir -p "$PAGAN_ROOT/$dir" done mkdir -p "$PAGAN_ROOT/usr/bin" "$PAGAN_ROOT/usr/sbin" # Katalogi PaganOS Package Infrastructure mkdir -p "$PAGAN_ROOT/var/lib/pag"{,/packages,/snapshots} mkdir -p "$PAGAN_ROOT/var/cache/pag" mkdir -p "$PAGAN_ROOT/var/cache/pagbuild"{/sources,/output} mkdir -p "$PAGAN_ROOT/var/lib/pagan-build/rootfs" mkdir -p "$PAGAN_ROOT/var/lib/pagan-sync/recipes" mkdir -p "$PAGAN_ROOT/var/www/repo.paganlinux.eu" mkdir -p "$PAGAN_ROOT/opt/pagan" # Deploymenty dla atomic updates mkdir -p "$PAGAN_ROOT/.deployments" ok "Środowisko zainicjowane w: $PAGAN_ROOT" } _archive_is_valid() { local file="$1" [[ -s "$file" ]] || return 1 case "$file" in *.tar.xz) xz -t "$file" >/dev/null 2>&1 ;; *.tar.gz|*.tgz) gzip -t "$file" >/dev/null 2>&1 ;; *.tar.bz2|*.tbz2) bzip2 -t "$file" >/dev/null 2>&1 ;; *.tar.zst) if command -v zstd >/dev/null 2>&1; then zstd -t "$file" >/dev/null 2>&1 else unzstd -t "$file" >/dev/null 2>&1 fi ;; *.tar) tar -tf "$file" >/dev/null 2>&1 ;; *.zip) unzip -tqq "$file" >/dev/null 2>&1 ;; *) ! file "$file" 2>/dev/null | grep -qE "HTML document|XML document|ASCII text|empty" ;; esac } download_pkg() { local url="$1" dest="$2" sha="${3:-SKIP}" force="${4:-0}" mkdir -p "$(dirname "$dest")" if [[ "$force" != "1" && -f "$dest" ]]; then if _archive_is_valid "$dest"; then info " ⏭ $(basename "$dest") – już pobrany" return 0 fi warn "Uszkodzone archiwum: $(basename "$dest") – pobieram ponownie" rm -f "$dest" fi wget --no-check-certificate -q --show-progress -O "$dest" "$url" 2>/dev/null || \ curl -# -L -o "$dest" "$url" 2>/dev/null || \ error "Nie udało się pobrać: $url" if ! _archive_is_valid "$dest"; then warn "Pobrano stronę HTML zamiast archiwum – próbuję mirror..." case "$url" in *download.savannah.gnu.org*) local alt_url alt_url=$(echo "$url" | sed 's|https://download.savannah.gnu.org|https://mirror.rabisu.com/mirrors/savannah|') wget --no-check-certificate -q --show-progress -O "$dest" "$alt_url" 2>/dev/null || \ curl -# -L -o "$dest" "$alt_url" 2>/dev/null || \ error "Nie udało się pobrać (mirror): $alt_url" _archive_is_valid "$dest" || error "Pobrany plik jest uszkodzony: $alt_url" ;; *) error "Pobrano uszkodzony plik z: $url" ;; esac fi info " ✓ $(basename "$dest")" } build_lfs_pkg() { local pkg_name="$1" pkg_version="$2" pkg_url="$3" pkg_sha="$4" pkg_config="$5" local archive; archive=$(basename "$pkg_url" | sed 's/?.*//') local archive_path="$SRC_DIR/$archive" local pkg_dir="$SRC_DIR/build-${pkg_name}" ((UI_PKG_N++)) || true if _is_built "${pkg_name}-${pkg_version}"; then ui_skip "${pkg_name}-${pkg_version}" ((PKG_SKIPPED++)) || true return 0 fi info " Budowanie: ${pkg_name}-${pkg_version}" download_pkg "$pkg_url" "$archive_path" "$pkg_sha" rm -rf "$pkg_dir" mkdir -p "$pkg_dir" local _strip="" local _tar_first tar tf "$archive_path" > /tmp/_tar_first.tmp 2>/dev/null || true _tar_first=$(sed -n '1p' /tmp/_tar_first.tmp 2>/dev/null) rm -f /tmp/_tar_first.tmp if [[ "$_tar_first" == *"/"* ]]; then _strip="--strip-components=1"; fi case "$archive" in *.tar.xz|*.tar.gz|*.tar.bz2) tar -xf "$archive_path" -C "$pkg_dir" $_strip ;; *.tar.zst) unzstd -d "$archive_path" -o "$SRC_DIR/${archive%.zst}" && tar -xf "$SRC_DIR/${archive%.zst}" -C "$pkg_dir" $_strip ;; *) tar -xf "$archive_path" -C "$pkg_dir" $_strip ;; esac || { warn "Rozpakowanie $pkg_name nieudane – wymuszam ponowne pobranie i retry" rm -f "$archive_path" "$SRC_DIR/${archive%.zst}" download_pkg "$pkg_url" "$archive_path" "$pkg_sha" 1 case "$archive" in *.tar.xz|*.tar.gz|*.tar.bz2) tar -xf "$archive_path" -C "$pkg_dir" $_strip ;; *.tar.zst) unzstd -d "$archive_path" -o "$SRC_DIR/${archive%.zst}" && tar -xf "$SRC_DIR/${archive%.zst}" -C "$pkg_dir" $_strip ;; *) tar -xf "$archive_path" -C "$pkg_dir" $_strip ;; esac || error "Rozpakowanie $pkg_name nieudane" } pushd "$pkg_dir" > /dev/null local pkg_log="$UI_LOG_DIR/${pkg_name}-${pkg_version}.log" if [[ -n "$pkg_config" && "$pkg_config" != "SKIP" ]]; then ui_build_eval "${pkg_name}-${pkg_version}" "$pkg_log" "$pkg_config" \ || error "Configure failed for $pkg_name (log: $pkg_log)" fi local _skip_auto_make=0 case "$pkg_config" in *"cp -"*|*"cp "*|*"make install"*|*"DESTDIR="*|*"ninja"*|*"pip3"*|*"pip install"*|*"cmake --install"*|*"./bootstrap"*|*"install -m"*|*"PREFIX="*) _skip_auto_make=1 ;; make*) _skip_auto_make=1 ;; esac if [[ $_skip_auto_make -eq 0 ]]; then ui_build_eval "${pkg_name}-${pkg_version} (make)" "$pkg_log" "make $MAKEFLAGS && make install" \ || error "Make/Install failed for $pkg_name (log: $pkg_log)" fi popd > /dev/null rm -rf "$pkg_dir" # Remove .la files (libtool archives) – hardcoded host paths break later links find "$PAGAN_ROOT/usr/lib" -name "*.la" -delete 2>/dev/null || true # Fix .pc files: rewrite prefix paths so pkg-config sees target sysroot for pc in "$PAGAN_ROOT/usr/lib/pkgconfig/"*.pc "$PAGAN_ROOT/usr/share/pkgconfig/"*.pc; do if [[ -f "$pc" ]]; then sed -i 's|^prefix=/usr$|prefix='"$PAGAN_ROOT"'/usr|' "$pc" sed -i '/^Cflags:/ { s/ -I\${includedir} / /g; s/^-I\${includedir} //; s/ -I\${includedir}$// }' "$pc" fi done 2>/dev/null || true _mark_built "${pkg_name}-${pkg_version}" ok " ✅ Zbudowano: $pkg_name-$pkg_version" } # ========================= TOOLCHAIN (Ch. 5) ========================= build_toolchain() { step "ROZDZIAŁ 5: BUDOWA TOOLCHAIN" ui_set_total 7 export LC_ALL=POSIX export LFS="$PAGAN_ROOT" export LFS_TGT="$LFS_TGT" build_lfs_pkg "linux-headers-tc" "$KERNEL_VERSION" "$KERNEL_URL" "SKIP" \ "make mrproper && make headers && find usr/include -type f ! -name '*.h' -delete && cp -rv usr/include $PAGAN_ROOT/usr" build_lfs_pkg "gmp-tc" "6.3.0" "https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz" "SKIP" \ "CFLAGS='-std=gnu89 -O2' ./configure --prefix=$TOOLS_DIR --enable-cxx --disable-shared --enable-static && make CFLAGS='-O2' $MAKEFLAGS && make install" build_lfs_pkg "mpfr-tc" "4.2.1" "https://ftp.gnu.org/gnu/mpfr/mpfr-4.2.1.tar.xz" "SKIP" \ "CFLAGS='-std=gnu89 -O2' ./configure --prefix=$TOOLS_DIR --disable-shared --enable-static --with-gmp=$TOOLS_DIR && make CFLAGS='-O2' $MAKEFLAGS && make install" build_lfs_pkg "mpc-tc" "1.3.1" "https://ftp.gnu.org/gnu/mpc/mpc-1.3.1.tar.gz" "SKIP" \ "CFLAGS='-std=gnu89 -O2' ./configure --prefix=$TOOLS_DIR --disable-shared --enable-static --with-gmp=$TOOLS_DIR --with-mpfr=$TOOLS_DIR && make CFLAGS='-O2' $MAKEFLAGS && make install" export PATH="$TOOLS_DIR/bin:$PATH" build_lfs_pkg "binutils-pass1" "2.43.1" "https://ftp.gnu.org/gnu/binutils/binutils-2.43.1.tar.xz" "SKIP" \ "mkdir -v build && cd build && ../configure --prefix=$TOOLS_DIR --with-sysroot=$PAGAN_ROOT --target=$LFS_TGT --disable-nls --enable-gprofng=no --disable-werror --disable-dependency-tracking && make $MAKEFLAGS && make install" build_lfs_pkg "gcc-pass1" "14.2.0" "https://ftp.gnu.org/gnu/gcc/gcc-14.2.0/gcc-14.2.0.tar.xz" "SKIP" \ 'case $(uname -m) in x86_64) sed -e "/m64=/s/lib64/lib/" -i.orig gcc/config/i386/t-linux64 ;; esac; sed -i "s/__cplusplus != 201103/__cplusplus < 201103/g; s/__cplusplus > 201103/__cplusplus < 201103/g" libcody/configure 2>/dev/null || true; sed -i "/^#include \"safe-ctype.h\"/i #ifdef __cplusplus\n#include \n#endif" gcc/system.h 2>/dev/null || true; sed -i "/^#include \"safe-ctype.h\"/a #ifdef __cplusplus\n#undef isalpha\n#undef isalnum\n#undef iscntrl\n#undef isdigit\n#undef isgraph\n#undef islower\n#undef isprint\n#undef ispunct\n#undef isspace\n#undef isupper\n#undef isxdigit\n#undef toupper\n#undef tolower\n#endif" gcc/system.h 2>/dev/null || true; mkdir -v build && cd build && ../configure --target='"$LFS_TGT"' --prefix='"$TOOLS_DIR"' --with-gmp='"$TOOLS_DIR"' --with-mpfr='"$TOOLS_DIR"' --with-mpc='"$TOOLS_DIR"' --with-glibc-version=2.44 --with-sysroot='"$PAGAN_ROOT"' --with-newlib --without-headers --enable-default-pie --enable-default-ssp --disable-nls --disable-shared --disable-multilib --disable-threads --disable-libatomic --disable-libgomp --disable-libquadmath --disable-libssp --disable-libvtv --disable-libstdcxx --enable-languages=c,c++ --enable-werror=no CXXFLAGS="-std=gnu++20 -O2 -Wno-error=return-type -fno-char8_t -Wno-deprecated-enum-enum-conversion" && make '"$MAKEFLAGS"' && make install && cd .. && ln -sf '"$LFS_TGT"'-gcc '"$CROSS_BIN"'/cc' build_lfs_pkg "glibc-tc" "2.44" "https://ftp.gnu.org/gnu/glibc/glibc-2.44.tar.xz" "SKIP" \ "rm -rf $PAGAN_ROOT/usr/include/gnu $PAGAN_ROOT/usr/include/features.h $PAGAN_ROOT/usr/include/stdc-predef.h 2>/dev/null; mkdir -v build && cd build && ../configure --prefix=/usr --host=$LFS_TGT --build=\$(../scripts/config.guess) --enable-kernel=4.14 --with-headers=$PAGAN_ROOT/usr/include libc_cv_slibdir=/usr/lib --disable-werror CFLAGS=\"-O2 -Wno-error=maybe-uninitialized\" && make $MAKEFLAGS && make DESTDIR=$PAGAN_ROOT install" ok "Toolchain zbudowany!" } # ========================= PEŁNY SYSTEM KOŃCOWY (Ch. 6) ========================= build_final_system() { step "ROZDZIAŁ 6-8: PEŁNY SYSTEM KOŃCOWY LFS 13.0" export PATH="$TOOLS_DIR/bin:/usr/bin/core_perl:/usr/bin/vendor_perl:$PATH" export LC_ALL=POSIX # Globalna kompatybilność z GCC 16 export CFLAGS="-std=gnu17 -O2 -Wno-error=implicit-function-declaration -Wno-error=int-conversion -Wno-error=return-type -Wno-error=maybe-uninitialized -Wno-error=discarded-qualifiers -Wno-error=unterminated-string-initialization -Wno-error=incompatible-pointer-types -Wno-error=null-dereference -Wno-error=override-init" export CXXFLAGS="-O2 -Wno-error=return-type -Wno-error=maybe-uninitialized" export FORCE_UNSAFE_CONFIGURE=1 export PKG_CONFIG_DIR="" export PKG_CONFIG_PATH="$PAGAN_ROOT/usr/lib/pkgconfig:$PAGAN_ROOT/usr/lib/x86_64-linux-gnu/pkgconfig:$PAGAN_ROOT/usr/share/pkgconfig" export PKG_CONFIG_SYSROOT_DIR="$PAGAN_ROOT" export PKG_CONFIG_LIBDIR="$PAGAN_ROOT/usr/lib/pkgconfig:$PAGAN_ROOT/usr/lib/x86_64-linux-gnu/pkgconfig:$PAGAN_ROOT/usr/share/pkgconfig" # Linkuj z targetowymi libami (glibc 2.44, zgodne z hostem) # UWAGA: brak globalnego CPPFLAGS=-I$PAGAN_ROOT/usr/include — glibc budując sam siebie # nie może mieć -I na zainstalowane headery glibc (guard _LIBC w gnu/stubs-64.h) export LDFLAGS="-L$PAGAN_ROOT/usr/lib -L$PAGAN_ROOT/lib64 -Wl,-rpath-link,$PAGAN_ROOT/usr/lib -Wl,-rpath-link,$PAGAN_ROOT/lib64" local packages=( "man-pages:6.17:https://www.kernel.org/pub/linux/docs/man-pages/man-pages-6.17.tar.xz:SKIP:make -R prefix=/usr install" "iana-etc:20260202:https://github.com/Mic92/iana-etc/releases/download/20260202/iana-etc-20260202.tar.gz:SKIP:cp services protocols \$PAGAN_ROOT/etc" "tzdata:2025c:https://www.iana.org/time-zones/repository/releases/tzdata2025c.tar.gz:SKIP:ZONEINFO=\$PAGAN_ROOT/usr/share/zoneinfo && mkdir -p \$ZONEINFO && cp -r ./* \$ZONEINFO/" "glibc:2.44:https://ftp.gnu.org/gnu/glibc/glibc-2.44.tar.xz:SKIP:mkdir bld && cd bld && ../configure --prefix=/usr --enable-kernel=4.14 --enable-stack-protector=strong libc_cv_slibdir=/usr/lib --disable-werror CFLAGS=\"-O2 -Wno-error=maybe-uninitialized\" && make && make install DESTDIR=\$PAGAN_ROOT && mkdir -p \$PAGAN_ROOT/lib64 && ln -sf ../usr/lib/ld-linux-x86-64.so.2 \$PAGAN_ROOT/lib64/ld-linux-x86-64.so.2" "zlib:1.3.2:https://zlib.net/fossils/zlib-1.3.2.tar.gz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "bzip2:1.0.8:https://www.sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz:SKIP:CC=gcc make -f Makefile-libbz2_so && CC=gcc make install PREFIX=\$PAGAN_ROOT/usr" "xz:5.8.2:https://github.com/tukaani-project/xz/releases/download/v5.8.2/xz-5.8.2.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "zstd:1.5.7:https://github.com/facebook/zstd/releases/download/v1.5.7/zstd-1.5.7.tar.gz:SKIP:CC=gcc make prefix=/usr && CC=gcc make prefix=/usr DESTDIR=\$PAGAN_ROOT install" "lz4:1.10.0:https://github.com/lz4/lz4/releases/download/v1.10.0/lz4-1.10.0.tar.gz:SKIP:CC=gcc make && CC=gcc make PREFIX=/usr DESTDIR=\$PAGAN_ROOT install" "readline:8.3:https://ftp.gnu.org/gnu/readline/readline-8.3.tar.gz:SKIP:./configure --prefix=/usr --disable-static --with-curses && make SHLIB_LIBS=-lncurses && make install DESTDIR=\$PAGAN_ROOT" "gmp:6.3.0:https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz:SKIP:./configure --prefix=/usr --enable-cxx --disable-static CFLAGS=\"-O2 -std=gnu89\" && make CFLAGS=\"-O2\" && make install DESTDIR=\$PAGAN_ROOT" "mpfr:4.2.2:https://ftp.gnu.org/gnu/mpfr/mpfr-4.2.2.tar.xz:SKIP:./configure --prefix=/usr --disable-static --enable-thread-safe && make && make install DESTDIR=\$PAGAN_ROOT" "mpc:1.3.1:https://ftp.gnu.org/gnu/mpc/mpc-1.3.1.tar.gz:SKIP:./configure --prefix=/usr --disable-static && make && make install DESTDIR=\$PAGAN_ROOT" "gcc:15.2.0:https://ftp.gnu.org/gnu/gcc/gcc-15.2.0/gcc-15.2.0.tar.xz:SKIP:sed -i 's/__cplusplus != 201103/__cplusplus < 201103/g; s/__cplusplus > 201103/__cplusplus < 201103/g' libcody/configure 2>/dev/null || true; mkdir build && cd build && ../configure --prefix=/usr --enable-languages=c,c++,fortran --enable-default-pie --enable-default-ssp --disable-multilib --disable-bootstrap --with-system-zlib --without-isl CXXFLAGS='-O2 -fno-char8_t' --disable-libsanitizer && make \$MAKEFLAGS && make DESTDIR=\$PAGAN_ROOT install && ln -sf gcc \$PAGAN_ROOT/usr/bin/cc" "attr:2.5.2:https://download.savannah.gnu.org/releases/attr/attr-2.5.2.tar.gz:SKIP:./configure --prefix=/usr --sysconfdir=/etc --disable-static && make && make install DESTDIR=\$PAGAN_ROOT" "acl:2.3.2:https://download.savannah.gnu.org/releases/acl/acl-2.3.2.tar.xz:SKIP:./configure --prefix=/usr --sysconfdir=/etc --disable-static && make && make install DESTDIR=\$PAGAN_ROOT" "libcap:2.77:https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/libcap-2.77.tar.xz:SKIP:CC=gcc make prefix=/usr lib=lib && CC=gcc make prefix=/usr lib=lib DESTDIR=\$PAGAN_ROOT install" "libxcrypt:4.5.2:https://github.com/besser82/libxcrypt/releases/download/v4.5.2/libxcrypt-4.5.2.tar.xz:SKIP:./configure --prefix=/usr --enable-hashes=strong,glibc --disable-static CFLAGS=\"-O2 -Wno-error=discarded-qualifiers -Wno-error=unterminated-string-initialization\" && make && make install DESTDIR=\$PAGAN_ROOT" "pcre2:10.47:https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.47/pcre2-10.47.tar.bz2:SKIP:./configure --prefix=/usr --enable-unicode --disable-static && make && make install DESTDIR=\$PAGAN_ROOT" "elfutils:0.194:https://sourceware.org/ftp/elfutils/0.194/elfutils-0.194.tar.bz2:SKIP:./configure --prefix=/usr --disable-debuginfod --disable-libdebuginfod --disable-werror && make && make -C libelf install DESTDIR=\$PAGAN_ROOT" "libffi:3.5.2:https://github.com/libffi/libffi/releases/download/v3.5.2/libffi-3.5.2.tar.gz:SKIP:./configure --prefix=/usr --disable-static && make && make install DESTDIR=\$PAGAN_ROOT" "file:5.46:https://astron.com/pub/file/file-5.46.tar.gz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "m4:1.4.21:https://ftp.gnu.org/gnu/m4/m4-1.4.21.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "bc:7.0.3:https://github.com/gavinhoward/bc/releases/download/7.0.3/bc-7.0.3.tar.xz:SKIP:CC=gcc CFLAGS=\"-std=c99 -O2\" ./configure --prefix=/usr -G -O3 && make && make install DESTDIR=\$PAGAN_ROOT" "flex:2.6.4:https://github.com/westes/flex/releases/download/v2.6.4/flex-2.6.4.tar.gz:SKIP:./configure --prefix=/usr --disable-static && make && make install DESTDIR=\$PAGAN_ROOT && ln -sf flex \$PAGAN_ROOT/usr/bin/lex" "bison:3.8.2:https://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "autoconf:2.72:https://ftp.gnu.org/gnu/autoconf/autoconf-2.72.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "automake:1.18.1:https://ftp.gnu.org/gnu/automake/automake-1.18.1.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "libtool:2.5.4:https://ftp.gnu.org/gnu/libtool/libtool-2.5.4.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "expat:2.7.4:https://github.com/libexpat/libexpat/releases/download/R_2_7_4/expat-2.7.4.tar.xz:SKIP:./configure --prefix=/usr --disable-static && make && make install DESTDIR=\$PAGAN_ROOT" # libxml2 – potrzebny gettextowi (msgfmt) i pakietom zależnym; soname libxml2.so.16 (od 2.15) "libxml2:2.15.3:https://download.gnome.org/sources/libxml2/2.15/libxml2-2.15.3.tar.xz:SKIP:CC=gcc ./configure --prefix=/usr --without-python --disable-static && make && make install DESTDIR=\$PAGAN_ROOT" # libunistring + libidn2 – runtime dep cmake (libidn2.so.0) "libunistring:1.2:https://mirrors.kernel.org/gnu/libunistring/libunistring-1.2.tar.xz:SKIP:CC=gcc ./configure --prefix=/usr --disable-static && make && make install DESTDIR=\$PAGAN_ROOT && rm -f \$PAGAN_ROOT/usr/lib/libunistring.la" "libidn2:2.3.7:https://mirrors.kernel.org/gnu/libidn/libidn2-2.3.7.tar.gz:SKIP:CC=gcc ./configure --prefix=/usr --disable-static --disable-doc --with-libunistring-prefix=\$PAGAN_ROOT/usr && make && make install DESTDIR=\$PAGAN_ROOT" "gettext:0.22.5:https://ftp.gnu.org/gnu/gettext/gettext-0.22.5.tar.xz:SKIP:./configure --prefix=/usr --disable-static --disable-acl && make && make install DESTDIR=\$PAGAN_ROOT" "ncurses:6.6:https://invisible-mirror.net/archives/ncurses/ncurses-6.6.tar.gz:SKIP:./configure --prefix=/usr --with-shared --without-debug --without-normal --enable-widec && make && make install DESTDIR=\$PAGAN_ROOT && for lib in ncurses form panel menu; do ln -sfv lib\${lib}w.so \$PAGAN_ROOT/usr/lib/lib\${lib}.so 2>/dev/null; done && ln -sfv libncursesw.so \$PAGAN_ROOT/usr/lib/libtinfo.so 2>/dev/null" "bash:5.3:https://ftp.gnu.org/gnu/bash/bash-5.3.tar.gz:SKIP:./configure --prefix=/usr --without-bash-malloc --with-installed-readline && make && make install DESTDIR=\$PAGAN_ROOT && ln -sf /usr/bin/bash \$PAGAN_ROOT/bin/sh && ln -sf /usr/bin/bash \$PAGAN_ROOT/bin/bash" "coreutils:9.10:https://ftp.gnu.org/gnu/coreutils/coreutils-9.10.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "diffutils:3.12:https://ftp.gnu.org/gnu/diffutils/diffutils-3.12.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "findutils:4.10.0:https://ftp.gnu.org/gnu/findutils/findutils-4.10.0.tar.xz:SKIP:./configure --prefix=/usr --localstatedir=/var/lib/locate && make && make install DESTDIR=\$PAGAN_ROOT" "gawk:5.3.2:https://ftp.gnu.org/gnu/gawk/gawk-5.3.2.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "grep:3.12:https://ftp.gnu.org/gnu/grep/grep-3.12.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "gzip:1.14:https://ftp.gnu.org/gnu/gzip/gzip-1.14.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "make:4.4.1:https://ftp.gnu.org/gnu/make/make-4.4.1.tar.gz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "patch:2.8:https://ftp.gnu.org/gnu/patch/patch-2.8.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "sed:4.9:https://ftp.gnu.org/gnu/sed/sed-4.9.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "tar:1.35:https://ftp.gnu.org/gnu/tar/tar-1.35.tar.xz:SKIP:sed -i 's/acl_get_file_at/tar_acl_get_file_at/g; s/acl_set_file_at/tar_acl_set_file_at/g; s/acl_delete_def_file_at/tar_acl_delete_def_file_at/g' src/xattrs.c && ./configure --prefix=/usr --without-posix-acls && make && make install DESTDIR=\$PAGAN_ROOT" "openssl:3.6.1:https://github.com/openssl/openssl/releases/download/openssl-3.6.1/openssl-3.6.1.tar.gz:SKIP:./Configure --prefix=/usr --openssldir=/etc/ssl --libdir=lib shared zlib-dynamic && make && make install DESTDIR=\$PAGAN_ROOT" "libbsd:0.12.2:https://libbsd.freedesktop.org/releases/libbsd-0.12.2.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "shadow:4.19.3:https://github.com/shadow-maint/shadow/releases/download/4.19.3/shadow-4.19.3.tar.xz:SKIP:./configure --prefix=/usr --sysconfdir=/etc --with-group-name-max-length=32 && make && make install DESTDIR=\$PAGAN_ROOT" "util-linux:2.41.3:https://www.kernel.org/pub/linux/utils/util-linux/v2.41/util-linux-2.41.3.tar.xz:SKIP:./configure --bindir=/usr/bin --libdir=/usr/lib --sbindir=/usr/sbin --disable-chfn-chsh --disable-login --disable-nologin --disable-su --disable-runuser --disable-pylibmount --disable-liblastlog2 --without-python --without-systemd && make && make install DESTDIR=\$PAGAN_ROOT" "e2fsprogs:1.47.3:https://downloads.sourceforge.net/project/e2fsprogs/e2fsprogs/v1.47.3/e2fsprogs-1.47.3.tar.gz:SKIP:mkdir bld && cd bld && ../configure --prefix=/usr --sysconfdir=/etc --enable-elf-shlibs --disable-fuse2fs && make && make install DESTDIR=\$PAGAN_ROOT" "procps-ng:4.0.6:https://sourceforge.net/projects/procps-ng/files/Production/procps-ng-4.0.6.tar.xz:SKIP:./configure --prefix=/usr --disable-static --disable-kill --without-ncurses && make && make install DESTDIR=\$PAGAN_ROOT" "kmod:34.2:https://www.kernel.org/pub/linux/utils/kernel/kmod/kmod-34.2.tar.xz:SKIP:./configure --prefix=/usr --sysconfdir=/etc --disable-manpages --with-openssl --with-xz --with-zstd --with-zlib && make && make install DESTDIR=\$PAGAN_ROOT" "grub:2.14:https://ftp.gnu.org/gnu/grub/grub-2.14.tar.xz:SKIP:touch grub-core/extra_deps.lst && ./configure --prefix=/usr --sysconfdir=/etc --disable-werror --with-platform=efi && make && make install DESTDIR=\$PAGAN_ROOT" "sqlite:3510200:https://sqlite.org/2026/sqlite-autoconf-3510200.tar.gz:SKIP:CC=gcc ./configure --prefix=/usr --disable-static --enable-fts5 && make && make install DESTDIR=\$PAGAN_ROOT" "gdbm:1.26:https://ftp.gnu.org/gnu/gdbm/gdbm-1.26.tar.gz:SKIP:./configure --prefix=/usr --disable-static --enable-libgdbm-compat && make && make install DESTDIR=\$PAGAN_ROOT" "gperf:3.3:https://ftp.gnu.org/gnu/gperf/gperf-3.3.tar.gz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "texinfo:7.2:https://ftp.gnu.org/gnu/texinfo/texinfo-7.2.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "less:692:https://www.greenwoodsoftware.com/less/less-692.tar.gz:SKIP:./configure --prefix=/usr --sysconfdir=/etc && make && make install DESTDIR=\$PAGAN_ROOT" "libpipeline:1.5.8:https://download.savannah.gnu.org/releases/libpipeline/libpipeline-1.5.8.tar.gz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "man-db:2.13.1:https://download.savannah.gnu.org/releases/man-db/man-db-2.13.1.tar.xz:SKIP:./configure --prefix=/usr --sysconfdir=/etc --disable-setuid && make && make install DESTDIR=\$PAGAN_ROOT" "psmisc:23.7:https://sourceforge.net/projects/psmisc/files/psmisc/psmisc-23.7.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "vim:9.2.0078:https://github.com/vim/vim/archive/v9.2.0078/vim-9.2.0078.tar.gz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT && ln -sf vim \$PAGAN_ROOT/usr/bin/vi" "kbd:2.9.0:https://www.kernel.org/pub/linux/utils/kbd/kbd-2.9.0.tar.xz:SKIP:./configure --prefix=/usr --disable-vlock && make && make install DESTDIR=\$PAGAN_ROOT" "inetutils:2.7:https://ftp.gnu.org/gnu/inetutils/inetutils-2.7.tar.gz:SKIP:./configure --prefix=/usr --disable-logger --disable-whois --disable-servers && make && make install DESTDIR=\$PAGAN_ROOT" "iproute2:6.18.0:https://www.kernel.org/pub/linux/utils/net/iproute2/iproute2-6.18.0.tar.xz:SKIP:sed -i /ARPD/d Makefile && make && make DESTDIR=\$PAGAN_ROOT SBINDIR=/usr/sbin install" "intltool:0.51.0:https://deb.debian.org/debian/pool/main/i/intltool/intltool_0.51.0.orig.tar.gz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "groff:1.23.0:https://ftp.gnu.org/gnu/groff/groff-1.23.0.tar.gz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "sysklogd:2.7.2:https://github.com/troglobit/sysklogd/releases/download/v2.7.2/sysklogd-2.7.2.tar.gz:SKIP:./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var && make && make install DESTDIR=\$PAGAN_ROOT" "tcl:8.6.17:https://downloads.sourceforge.net/tcl/tcl8.6.17-src.tar.gz:SKIP:cd unix && ./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "perl:5.42.0:https://www.cpan.org/src/5.0/perl-5.42.0.tar.xz:SKIP:sh Configure -des -Dcc=gcc -Dprefix=/usr -Duseshrplib && make && make install DESTDIR=\$PAGAN_ROOT" "python:3.14.3:https://www.python.org/ftp/python/3.14.3/Python-3.14.3.tar.xz:SKIP:sed -i 's|^@MODULE__CRYPT_TRUE@_crypt|#_crypt|' Modules/Setup.stdlib.in && ac_cv_lib_crypt_crypt_r=no ac_cv_func_crypt_r=no ./configure --prefix=/usr --enable-shared && make && make install DESTDIR=\$PAGAN_ROOT" "ninja:1.13.2:https://github.com/ninja-build/ninja/archive/v1.13.2/ninja-1.13.2.tar.gz:SKIP:python3 configure.py --bootstrap && install -m755 ninja \$PAGAN_ROOT/usr/bin/" "meson:1.10.1:https://github.com/mesonbuild/meson/releases/download/1.10.1/meson-1.10.1.tar.gz:SKIP:pip3 wheel -w dist --no-build-isolation --no-deps \$PWD && pip3 install --no-index --find-links dist --root=\$PAGAN_ROOT meson" "cmake:3.31.6:https://github.com/Kitware/CMake/releases/download/v3.31.6/cmake-3.31.6.tar.gz:SKIP:CC=gcc CXX=g++ CFLAGS= CXXFLAGS= cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF && cmake --build build \$MAKEFLAGS && DESTDIR=\$PAGAN_ROOT cmake --install build" "git:2.47.2:https://www.kernel.org/pub/software/scm/git/git-2.47.2.tar.xz:SKIP:./configure --prefix=/usr --with-openssl --with-curl --with-expat && make && make install DESTDIR=\$PAGAN_ROOT" # ======== SYSTEMD / DBUS / UDEV ======== "binutils:2.46.0:https://sourceware.org/pub/binutils/releases/binutils-2.46.0.tar.xz:SKIP:mkdir build && cd build && ../configure --prefix=/usr --sysconfdir=/etc --enable-lto --enable-gold --enable-ld=default --enable-plugins --enable-shared --disable-werror && make && make install DESTDIR=\$PAGAN_ROOT && cd .." # ======== DEJAGNU + TCL/EXPECT ======== "dejagnu:1.6.3:https://ftp.gnu.org/gnu/dejagnu/dejagnu-1.6.3.tar.gz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT" "expect:5.45.4:https://prdownloads.sourceforge.net/expect/expect5.45.4.tar.gz:SKIP:cp -f pty_termios.c pty_.c 2>/dev/null || true; echo '#include \"exp_tty.h\"' > exp_tty_hack.h; for f in exp_inter.c exp_main_sub.c exp_command.c; do sed -i '1i#include \"exp_tty_hack.h\"' \"\$f\" 2>/dev/null || true; done; ./configure --prefix=/usr --with-tcl=/usr/lib --enable-shared 2>/dev/null && make 2>/dev/null && make install DESTDIR=\$PAGAN_ROOT 2>/dev/null || true" # ======== SYSTEMD / DBUS / UDEV ======== "dbus:1.16.2:https://dbus.freedesktop.org/releases/dbus/dbus-1.16.2.tar.xz:SKIP:CC=gcc CXX=g++ cmake -B build -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_SYSCONFDIR=/etc -DCMAKE_INSTALL_LOCALSTATEDIR=/var -DDBUS_SYSTEMD_USER_SERVICE_DIR=/usr/lib/systemd/user -DDBUS_BUILD_TESTS=OFF && make -C build && make -C build DESTDIR=\$PAGAN_ROOT install" "udev-lfs:20230818:https://anduin.linuxfromscratch.org/LFS/udev-lfs-20230818.tar.xz:SKIP:mkdir -p udev-lfs-20230818 2>/dev/null; find . -maxdepth 1 -type f -exec cp {} udev-lfs-20230818/ \\; 2>/dev/null; make -f Makefile.lfs DESTDIR=\$PAGAN_ROOT install" "keyutils:1.6.3:https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/keyutils.git/snapshot/keyutils-1.6.3.tar.gz:SKIP:make NO_ARLIB=1 NO_SOLIB_DEP=1 BINDIR=/usr/bin SBINDIR=/usr/sbin LIBDIR=/usr/lib && make NO_ARLIB=1 NO_SOLIB_DEP=1 BINDIR=/usr/bin SBINDIR=/usr/sbin LIBDIR=/usr/lib DESTDIR=\$PAGAN_ROOT install" "systemd:259.1:https://github.com/systemd/systemd/archive/v259.1.tar.gz:SKIP:CFLAGS=\"\$CFLAGS -Wno-error=redundant-decls\" CXXFLAGS=\"\$CXXFLAGS -Wno-error=redundant-decls\" CC=gcc CXX=g++ meson setup build --prefix=/usr --sysconfdir=/etc --localstatedir=/var -Dmode=release -Dman=disabled -Ddefault-dnssec=no -Dwerror=false && ninja -C build && DESTDIR=\$PAGAN_ROOT ninja -C build install 2>/dev/null || true" "pkgconf:2.5.1:https://distfiles.ariadne.space/pkgconf/pkgconf-2.5.1.tar.xz:SKIP:./configure --prefix=/usr && make && make install DESTDIR=\$PAGAN_ROOT && ln -sf pkgconf \$PAGAN_ROOT/usr/bin/pkg-config" "sysvinit:3.14:https://github.com/slicer69/sysvinit/releases/download/3.14/sysvinit-3.14.tar.xz:SKIP:CC=gcc make -C src && make -C src DESTDIR=\$PAGAN_ROOT install" "XML-Parser:2.47:https://cpan.metacpan.org/authors/id/T/TO/TODDR/XML-Parser-2.47.tar.gz:SKIP:perl Makefile.PL && make && make install DESTDIR=\$PAGAN_ROOT" ) ui_set_total "${#packages[@]}" for pkg_info in "${packages[@]}"; do name="${pkg_info%%:*}"; rest="${pkg_info#*:}" ver="${rest%%:*}"; rest="${rest#*:}" config="${rest##*:}"; rest_no_cfg="${rest%:*}" sha="${rest_no_cfg##*:}" url="${rest_no_cfg%:*}" build_lfs_pkg "$name" "$ver" "$url" "$sha" "$config" done _configure_basic_system ok "System końcowy zbudowany!" } _configure_basic_system() { cat > "$PAGAN_ROOT/etc/passwd" <<'EOF' root:x:0:0:root:/root:/bin/bash nobody:x:65534:65534:nobody:/:/bin/false EOF cat > "$PAGAN_ROOT/etc/group" <<'EOF' root:x:0: bin:x:1: sys:x:2: kmem:x:3: tty:x:4: tape:x:5: daemon:x:6: floppy:x:7: disk:x:8: lp:x:9: dialout:x:10: audio:x:11: video:x:12: utmp:x:13: usb:x:14: cdrom:x:15: mail:x:34: nogroup:x:65534: EOF cat > "$PAGAN_ROOT/etc/fstab" <<'EOF' /dev/sda1 / ext4 defaults 0 1 proc /proc proc nosuid,noexec,nodev 0 0 sysfs /sys sysfs nosuid,noexec,nodev 0 0 devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 tmpfs /tmp tmpfs defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 shm /dev/shm tmpfs defaults 0 0 EOF } # ============================================================================= # INSTALACJA STOSU PAGAN OS (PAG, PAGBUILD, PAGSYNC) W ROOTFS # ============================================================================= install_pagan_toolstack() { step "INSTALACJA STOSU PAGAN OS (pag, pagbuild, pagbuild-sync)" info "1. Instalowanie modułów Pythona (PyYAML, Jinja2, Requests) w chroocie..." chroot "$PAGAN_ROOT" pip3 install flit-core packaging markupsafe jinja2 setuptools wheel pyyaml requests --break-system-packages 2>/dev/null || true # ------------------------------------------------------------------------- # A. Menedżer Pakietów: /usr/bin/pag (pełna wersja) # ------------------------------------------------------------------------- info "2. Kopiowanie pełnego pag..." cp "$SCRIPT_DIR/pag/pag" "$PAGAN_ROOT/usr/bin/pag" chmod +x "$PAGAN_ROOT/usr/bin/pag" # ------------------------------------------------------------------------- # A2. Kompilator Go – /usr/lib/go + symlinki /usr/bin/{go,gofmt} # ------------------------------------------------------------------------- info "2b. Instalowanie Go..." GO_VER="${GO_VER:-1.26.5}" GO_TARBALL="go${GO_VER}.linux-amd64.tar.gz" if [[ ! -d "$PAGAN_ROOT/usr/lib/go" ]]; then curl -fsSL -o "/tmp/$GO_TARBALL" "https://go.dev/dl/$GO_TARBALL" \ && mkdir -p "$PAGAN_ROOT/usr/lib" \ && tar -xzf "/tmp/$GO_TARBALL" -C "$PAGAN_ROOT/usr/lib/" \ && rm -f "/tmp/$GO_TARBALL" fi [[ -x "$PAGAN_ROOT/usr/lib/go/bin/go" ]] \ && ln -sf /usr/lib/go/bin/go "$PAGAN_ROOT/usr/bin/go" \ && ln -sf /usr/lib/go/bin/gofmt "$PAGAN_ROOT/usr/bin/gofmt" \ && ok "Go ${GO_VER} zainstalowany" || warn "Go: instalacja nieudana (pominięto)" # ------------------------------------------------------------------------- # B. Builder w Chroot: /usr/bin/pagbuild # ------------------------------------------------------------------------- info "3. Tworzenie narzędzia /usr/bin/pagbuild..." cat > "$PAGAN_ROOT/usr/bin/pagbuild" <<'PAGBUILD_BIN' #!/usr/bin/env bash # PAGBUILD – Builder Przepisów PAGBUILD.yaml dla PaganOS set -euo pipefail RECIPE_FILE="${1:-PAGBUILD.yaml}" ROOTFS="${ROOTFS:-/var/lib/pagan-build/rootfs}" OUT_DIR="${OUT_DIR:-/var/cache/pagbuild/output}" SRC_CACHE="${SRC_CACHE:-/var/cache/pagbuild/sources}" BUILD_WORK="/tmp/pagbuild-work" if [[ ! -f "$RECIPE_FILE" ]]; then echo "❌ Błąd: Przepis $RECIPE_FILE nie istnieje." exit 1 fi eval $(python3 -c " import yaml with open('$RECIPE_FILE') as f: data = yaml.safe_load(f) meta = data.get('package', {}) src = data.get('source', {}) print(f'PKG_NAME=\"{meta.get(\"name\", \"\")}\"') print(f'PKG_VER=\"{meta.get(\"version\", \"\")}\"') print(f'PKG_REL=\"{meta.get(\"release\", 1)}\"') print(f'PKG_CAT=\"{meta.get(\"category\", \"other\")}\"') print(f'SRC_URL=\"{src.get(\"url\", \"\")}\"') print(f'SRC_SHA256=\"{src.get(\"sha256\", \"\")}\"') ") FULL_NAME="${PKG_NAME}-${PKG_VER}-${PKG_REL}" echo "Budowanie przepisu PaganOS: $FULL_NAME ($PKG_CAT)" mkdir -p "$SRC_CACHE" "$OUT_DIR" "$BUILD_WORK" ARCHIVE_NAME=$(basename "$SRC_URL") CACHED_SRC="$SRC_CACHE/$ARCHIVE_NAME" if [[ -n "$SRC_URL" ]]; then if [[ ! -f "$CACHED_SRC" ]]; then curl -sSL "$SRC_URL" -o "$CACHED_SRC" fi fi WORK_DIR="$BUILD_WORK/$FULL_NAME" DESTDIR="$WORK_DIR/destdir" rm -rf "$WORK_DIR" mkdir -p "$WORK_DIR/src" "$DESTDIR" if [[ -f "$CACHED_SRC" ]]; then tar -xf "$CACHED_SRC" -C "$WORK_DIR/src" --strip-components=1 2>/dev/null || tar -xf "$CACHED_SRC" -C "$WORK_DIR/src" fi BUILD_SCRIPT="$WORK_DIR/build.sh" python3 -c " import yaml with open('$RECIPE_FILE') as f: data = yaml.safe_load(f) bld = data.get('build', {}) script = f'''#!/bin/bash set -eo pipefail export DESTDIR=/tmp/destdir cd /tmp/src {chr(10).join(bld.get('prepare', []))} {chr(10).join(bld.get('compile', []))} {chr(10).join(bld.get('install', []))} ''' with open('$BUILD_SCRIPT', 'w') as out: out.write(script) " chmod +x "$BUILD_SCRIPT" mkdir -p "$ROOTFS/tmp/src" "$ROOTFS/tmp/destdir" cp -r "$WORK_DIR/src/"* "$ROOTFS/tmp/src/" cp "$BUILD_SCRIPT" "$ROOTFS/tmp/build.sh" mount -t proc proc "$ROOTFS/proc" 2>/dev/null || true mount -t sysfs sys "$ROOTFS/sys" 2>/dev/null || true mount --bind /dev "$ROOTFS/dev" 2>/dev/null || true chroot "$ROOTFS" /usr/bin/env -i PATH=/usr/bin:/usr/sbin:/bin:/sbin /tmp/build.sh umount -l "$ROOTFS/dev" 2>/dev/null || true umount -l "$ROOTFS/sys" 2>/dev/null || true umount -l "$ROOTFS/proc" 2>/dev/null || true cp -r "$ROOTFS/tmp/destdir/"* "$DESTDIR/" 2>/dev/null || true python3 -c " import yaml, json with open('$RECIPE_FILE') as f: data = yaml.safe_load(f) meta = data.get('package', {}) pkg_info = {'name': meta.get('name'), 'version': meta.get('version'), 'category': meta.get('category', 'other')} with open('$DESTDIR/metadata.json', 'w') as f: json.dump(pkg_info, f, indent=2) " PKG_FILE="$OUT_DIR/${FULL_NAME}.pkg.tar.xz" tar -cJf "$PKG_FILE" -C "$DESTDIR" . echo "✅ Zbudowano pakiet PaganOS: $PKG_FILE" rm -rf "$WORK_DIR" PAGBUILD_BIN chmod +x "$PAGAN_ROOT/usr/bin/pagbuild" # Nie zostawiaj starego stubu z heredoca: rootfs ma zawierać ten sam # produkcyjny builder, którego używa pagsync na serwerze. if [[ -f "$SCRIPT_DIR/pagbuild" ]]; then cp -f "$SCRIPT_DIR/pagbuild" "$PAGAN_ROOT/usr/bin/pagbuild" chmod +x "$PAGAN_ROOT/usr/bin/pagbuild" fi if [[ -f "$SCRIPT_DIR/pagsync" ]]; then cp -f "$SCRIPT_DIR/pagsync" "$PAGAN_ROOT/opt/pagan/pagsync" chmod +x "$PAGAN_ROOT/opt/pagan/pagsync" fi # ------------------------------------------------------------------------- # C. Menedżer Kolejki & Synchronizacji: /opt/pagan/pagbuild-sync # ------------------------------------------------------------------------- info "4. Tworzenie /opt/pagan/pagbuild-sync..." cat > "$PAGAN_ROOT/opt/pagan/pagbuild-sync" <<'PAGSYNC_BIN' #!/usr/bin/env python3 """ PAGBUILD-SYNC – PaganOS Queue & Daemon Sync Manager """ import os, sys, json, time, argparse, subprocess from pathlib import Path STATE_FILE = "/var/lib/pagan-sync/state.json" RECIPES_DIR = "/var/lib/pagan-sync/recipes" REPO_BASE = "/var/www/repo.paganlinux.eu" BUILD_OUT = "/var/cache/pagbuild/output" PAGBUILD_BIN = "/usr/bin/pagbuild" CATEGORIES = ["core", "desktop", "tools", "network", "multimedia", "gaming", "office", "other"] def load_state(): if os.path.exists(STATE_FILE): try: with open(STATE_FILE, "r") as f: return json.load(f) except Exception: pass return {"builds": [], "last_sync": "", "current_build": None} def save_state(state): os.makedirs(os.path.dirname(STATE_FILE), exist_ok=True) with open(STATE_FILE, "w") as f: json.dump(state, f, indent=2) def run_single(pkg_name, recipe_path, cat, state): print(f"[BUILD] Start: {pkg_name} ({cat})") state["current_build"] = {"name": pkg_name, "category": cat, "start_time": time.strftime("%Y-%m-%d %H:%M:%S")} save_state(state) start = time.time() proc = subprocess.run([PAGBUILD_BIN, recipe_path], capture_output=True, text=True) dur = round(time.time() - start, 1) status = "ok" if proc.returncode == 0 else "failed" if status == "ok": print(f"✅ [BUILD] Sukces {pkg_name} w {dur}s") out_pkg = list(Path(BUILD_OUT).glob(f"{pkg_name}-*.pkg.tar.xz")) if out_pkg: dst = os.path.join(REPO_BASE, cat) os.makedirs(dst, exist_ok=True) subprocess.run(["mv", "-f", str(out_pkg[0]), dst]) else: print(f"❌ [BUILD] Błąd {pkg_name}: {proc.stderr[:200]}") state["builds"].append({"name": pkg_name, "category": cat, "status": status, "duration": f"{dur}s", "time": time.strftime("%Y-%m-%d %H:%M:%S")}) state["current_build"] = None save_state(state) def sync_all(force=False): state = load_state() for cat in CATEGORIES: cdir = os.path.join(RECIPES_DIR, cat) if not os.path.isdir(cdir): continue for pkg in sorted(os.listdir(cdir)): yml = os.path.join(cdir, pkg, "PAGBUILD.yaml") if not os.path.exists(yml): yml = os.path.join(cdir, pkg, "package.yml") if os.path.isfile(yml): run_single(pkg, yml, cat, state) if __name__ == "__main__": p = argparse.ArgumentParser() p.add_argument("--once", action="store_true") p.add_argument("--force", action="store_true") p.add_argument("--build", type=str, default=None) args = p.parse_args() if args.build: st = load_state() for c in CATEGORIES: y = os.path.join(RECIPES_DIR, c, args.build, "PAGBUILD.yaml") if os.path.exists(y): run_single(args.build, y, c, st); break else: sync_all(args.force) PAGSYNC_BIN chmod +x "$PAGAN_ROOT/opt/pagan/pagbuild-sync" ln -sf /opt/pagan/pagbuild-sync "$PAGAN_ROOT/usr/bin/pagsync" ok "PaganOS Toolstack zainstalowany pomyślnie!" } finalize_build() { step "FINALIZACJA BUDOWY PAGAN LINUX" cat > "$PAGAN_ROOT/etc/pagan-release" </dev/null || true # Pliki .la (libtool) są zbędne w runtime i potrafią zepsuć linkowanie (libdir=/usr/lib) find "$PAGAN_ROOT" -name "*.la" -delete 2>/dev/null || true ok "Finalizacja zakończona!" } # ========================= WERYFIKACJA ROOTFS ========================= verify_rootfs() { step "WERYFIKACJA ROOTFS – sanity check po buildzie" local fails=0 local check for check in bash sh ls cat grep sed awk make gcc python3 perl; do if [[ ! -x "$PAGAN_ROOT/usr/bin/$check" ]] && [[ ! -x "$PAGAN_ROOT/bin/$check" ]]; then warn "Brak binarki: $check" ((fails++)) || true fi done # Python + sqlite3 (wymagane przez pag) if [[ -x "$PAGAN_ROOT/usr/bin/python3" ]]; then if chroot "$PAGAN_ROOT" /usr/bin/python3 -c "import sqlite3; import zlib; import tarfile; print('python3: sqlite3 OK')" >/dev/null 2>&1; then ok "python3 + sqlite3 działa" else warn "python3 nie ma sqlite3/zlib/tarfile – pag nie będzie działać!" ((fails++)) || true fi else warn "Brak python3 – pag nie będzie działać!" ((fails++)) || true fi # pag – pełna wersja (nie stub) if [[ -f "$PAGAN_ROOT/usr/bin/pag" ]]; then if grep -q "PAG - Pagan Linux Package Manager v3" "$PAGAN_ROOT/usr/bin/pag" 2>/dev/null; then ok "pag – pełna wersja v3" else warn "pag to stub (niepełna wersja) – sprawdź install_pagan_toolstack" ((fails++)) || true fi else warn "Brak /usr/bin/pag" ((fails++)) || true fi # glibc if [[ -f "$PAGAN_ROOT/usr/lib/libc.so.6" ]]; then local glibc_ver glibc_ver=$(chroot "$PAGAN_ROOT" /usr/bin/ldd --version 2>/dev/null | head -1 | grep -o '[0-9.]*' || true) ok "glibc: ${glibc_ver:-?}" else warn "Brak libc.so.6!" ((fails++)) || true fi # Chroot test if chroot "$PAGAN_ROOT" /bin/bash -c "echo OK" >/dev/null 2>&1; then ok "chroot + bash działa" else warn "chroot /bin/bash NIE działa!" ((fails++)) || true fi if [[ $fails -gt 0 ]]; then warn "Weryfikacja: $fails problemów znalezionych (patrz wyżej)" else ok "Weryfikacja: wszystkie sanity checki przeszły ✅" fi return $fails } mount_virtual_fs() { mount --bind /dev "$PAGAN_ROOT/dev" 2>/dev/null || true mount --bind /dev/pts "$PAGAN_ROOT/dev/pts" 2>/dev/null || true mount -t proc proc "$PAGAN_ROOT/proc" 2>/dev/null || true mount -t sysfs sysfs "$PAGAN_ROOT/sys" 2>/dev/null || true mount -t tmpfs tmpfs "$PAGAN_ROOT/run" 2>/dev/null || true } umount_virtual_fs() { umount -l "$PAGAN_ROOT/dev/pts" 2>/dev/null || true umount -l "$PAGAN_ROOT/dev" 2>/dev/null || true umount -l "$PAGAN_ROOT/proc" 2>/dev/null || true umount -l "$PAGAN_ROOT/sys" 2>/dev/null || true umount -l "$PAGAN_ROOT/run" 2>/dev/null || true } # ========================= MAIN ========================= main() { cd / show_banner local arg for arg in "$@"; do case "$arg" in --rebuild|--from-scratch|--clean) REBUILD_FROM_SCRATCH=1 ;; esac done if [[ $EUID -ne 0 ]]; then error "Wymagane uprawnienia root (sudo)" fi if _is_true "${REBUILD_FROM_SCRATCH:-0}"; then clean_build_state fi # rootfs.sh ma budować wyłącznie rootfs (bez desktopów, kernela i obrazów) if [[ "${BUILD_IMG:-0}" -ne 0 || "${BUILD_ISO:-0}" -ne 0 ]]; then warn "Ten skrypt buduje tylko rootfs. Zmiennie BUILD_IMG/BUILD_ISO są ignorowane." fi check_dependencies check_lfs_patches init_build build_toolchain # Ch. 5 mount_virtual_fs build_final_system # Ch. 6-8 LFS + systemd install_pagan_toolstack # pag + pagbuild umount_virtual_fs finalize_build verify_rootfs # ===== TEST CHROOT ===== step "TEST CHROOT – sprawdzanie rootfs" local TARBALL="/tmp/pagan-rootfs-${PAGAN_VERSION}.tar.xz" if chroot "$PAGAN_ROOT" /bin/bash -c "echo OK && uname -a" 2>/dev/null; then ok "✅ Chroot działa poprawnie!" # ===== PAKOWANIE DO TAR.XZ ===== step "PAKOWANIE ROOTFS DO $TARBALL" info "Rozmiar rootfs: $(du -sh "$PAGAN_ROOT" --exclude="$PAGAN_ROOT/sources" 2>/dev/null | cut -f1)" rm -f "$TARBALL" tar -cJf "$TARBALL" \ -C "$PAGAN_ROOT" \ --exclude='./sources' \ --exclude='./proc' \ --exclude='./sys' \ --exclude='./dev' \ --exclude='./run' \ --exclude='./tmp' \ --exclude='./lost+found' \ . 2>/dev/null ok "Archiwum: $TARBALL ($(du -h "$TARBALL" 2>/dev/null | cut -f1))" echo "" echo " Aby wysłać na VPS:" echo " scp $TARBALL root@vps:/tmp/" echo " ssh root@vps 'rm -rf /mnt/pagan-rootfs && mkdir -p /mnt/pagan-rootfs && tar -xJf /tmp/pagan-rootfs-*.tar.xz -C /mnt/pagan-rootfs && chroot /mnt/pagan-rootfs /bin/bash'" else error "❌ Chroot NIE DZIAŁA! Sprawdź log: $LOG_FILE" fi step "✅ PAGANOS ROOTFS ZBUDOWANY – gotowy do pagbuild!" echo "" echo " Aby budować pakiety lokalnie:" echo " sudo chroot $PAGAN_ROOT /bin/bash" echo " pagbuild recipes/core/bash/PAGBUILD.yaml" echo " pag install /var/cache/pagbuild/output/bash-*.pkg.tar.xz" echo "" } if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi