yajl (needed by conmon, bootstrapped from source since Slackware ships no package for it) builds via CMake, not the cmake-free autoconf script its ./configure wrapper name suggests. Tracing the failure through the actual vbatts/slackware:15.0 image on the runner host surfaced a chain of packages slackpkg does not auto-resolve (Slackware packages carry no dependency metadata at all): cmake needs libarchive, which needs lz4 and libxml2; the patched make/gmake this mirror serves needs guile, which needs gc; compiling anything needs kernel-headers for <linux/errno.h>; and this build's binutils (ar/ranlib) needs flex, while objdump needs elfutils. All added to the same slackpkg install list as the rest of the toolchain, keeping everything on one mutually consistent version set. Verified end-to-end against vbatts/slackware:15.0 on the actual runner host at each step of this dependency chain. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
187 lines
8.8 KiB
Bash
Executable File
187 lines
8.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# =============================================================================
|
|
# scripts/ci/setup-slackware-buildenv.sh
|
|
#
|
|
# Prepares a Slackware container (see .github/workflows/build-packages.yml)
|
|
# to build all seven packages under packages/. Idempotent and safe to re-run.
|
|
#
|
|
# Strategy: vbatts/slackware:15.0 (the image build-packages.yml runs this
|
|
# in) is a minimal rootfs — it ships none of the 'D' (development) series,
|
|
# nor glib2/libcap/fuse3/curl. Step 0 below uses slackpkg (already present
|
|
# and pre-configured with a mirror in that image) to install the toolchain
|
|
# packages by name. Slackware packages carry no dependency metadata at all
|
|
# (unlike apt/dnf), so slackpkg does NOT resolve dependencies — the list
|
|
# below must name every package explicitly, including curl's HTTPS
|
|
# runtime libs (nghttp2, brotli, cyrus-sasl), or you get a shared-library
|
|
# error at the first invocation, not an install-time failure. What's left
|
|
# after this (libseccomp, yajl — neither ships in stock Slackware — plus
|
|
# the Go and Rust toolchains, which no Slackware install ships) is
|
|
# bootstrapped from source, further down. This makes the script tolerant
|
|
# of small differences between Slackware base image variants (it skips
|
|
# anything slackpkg reports as already installed) instead of assuming one
|
|
# exact image layout, while still failing loudly if something we cannot
|
|
# self-provision is missing.
|
|
#
|
|
# Exits non-zero with a clear message if a required tool cannot be found or
|
|
# provisioned — this script is meant to run early in CI so failures surface
|
|
# immediately, not halfway through a 20-minute podman build.
|
|
# =============================================================================
|
|
|
|
set -eu
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
# shellcheck source=/dev/null
|
|
. "$REPO_ROOT/scripts/ci/buildenv-versions.env"
|
|
|
|
WORK="/tmp/unraid-podman-buildenv"
|
|
mkdir -p "$WORK"
|
|
|
|
require_binary() {
|
|
local bin="$1" hint="$2"
|
|
if ! command -v "$bin" > /dev/null 2>&1; then
|
|
echo "!! Required tool '$bin' not found in the build image." >&2
|
|
echo "!! $hint" >&2
|
|
exit 1
|
|
fi
|
|
echo "==> found $bin: $(command -v "$bin")"
|
|
}
|
|
|
|
require_pkgconfig() {
|
|
local module="$1" hint="$2"
|
|
if ! pkg-config --exists "$module" 2>/dev/null; then
|
|
echo "!! Required library '$module' not found via pkg-config." >&2
|
|
echo "!! $hint" >&2
|
|
return 1
|
|
fi
|
|
echo "==> found pkg-config module: $module ($(pkg-config --modversion "$module"))"
|
|
return 0
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 0. Bootstrap the Slackware toolchain packages via slackpkg, if missing.
|
|
#
|
|
# CHECKGPG is turned off here: slackpkg's default GPG-key bootstrap fetches
|
|
# Slackware's signing key from www.slackware.com, which is not reachable
|
|
# from every CI network (observed to hang/fail on the self-hosted Gitea
|
|
# Actions runner this project builds on). slackpkg's CHECKMD5 (on by
|
|
# default) still verifies every package against the mirror's own
|
|
# CHECKSUMS.md5 as a transit-integrity check. This is build-toolchain
|
|
# provisioning, not the shipped artifacts — those are independently
|
|
# checksummed by scripts/checksums.sh.
|
|
# -----------------------------------------------------------------------------
|
|
if command -v slackpkg > /dev/null 2>&1; then
|
|
echo "==> bootstrapping build toolchain via slackpkg"
|
|
sed -i 's/^CHECKGPG=on/CHECKGPG=off/' /etc/slackpkg/slackpkg.conf
|
|
slackpkg -batch=on -default_answer=y update
|
|
slackpkg -batch=on -default_answer=y install \
|
|
gcc gcc-g++ binutils make m4 perl autoconf automake libtool pkg-config \
|
|
curl nghttp2 brotli cyrus-sasl ca-certificates glib2 libcap fuse3 \
|
|
cmake libarchive lz4 libxml2 guile gc kernel-headers flex elfutils
|
|
else
|
|
echo "==> slackpkg not found, assuming toolchain is already provided by the base image"
|
|
fi
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 1. Baseline toolchain expected to already be present in the base image.
|
|
# -----------------------------------------------------------------------------
|
|
require_binary gcc "Use a Slackware base image with the 'D' (development) series installed."
|
|
require_binary make "Use a Slackware base image with the 'D' (development) series installed."
|
|
require_binary autoconf "Needed by crun/fuse-overlayfs; part of Slackware's 'D' series."
|
|
require_binary automake "Needed by crun/fuse-overlayfs; part of Slackware's 'D' series."
|
|
require_binary libtool "Needed by crun/fuse-overlayfs; part of Slackware's 'D' series."
|
|
require_binary pkg-config "Needed to locate C library dependencies."
|
|
require_binary git "Needed to fetch crun's git submodules."
|
|
require_binary curl "Needed to fetch pinned source tarballs."
|
|
require_binary makepkg "Slackware's own packaging tool (pkgtools); should always be present."
|
|
require_binary strip "Part of binutils; part of Slackware's 'D' series."
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 2. C library dependencies expected to already be present.
|
|
# -----------------------------------------------------------------------------
|
|
require_pkgconfig glib-2.0 "Install Slackware's glib2 package (needed by conmon)."
|
|
require_pkgconfig libcap "Install Slackware's libcap package (needed by crun)." || true
|
|
require_pkgconfig fuse3 "Install Slackware's fuse3 package (needed by fuse-overlayfs)." || true
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 3. libseccomp — not part of stock Slackware, build from source if missing.
|
|
# -----------------------------------------------------------------------------
|
|
if ! pkg-config --exists libseccomp 2>/dev/null; then
|
|
echo "==> libseccomp not found, building v$LIBSECCOMP_VERSION from source"
|
|
d="$WORK/libseccomp"
|
|
mkdir -p "$d"
|
|
curl -fL --retry 3 -o "$d/src.tar.gz" "$LIBSECCOMP_SRC_URL"
|
|
actual=$(sha256sum "$d/src.tar.gz" | awk '{print $1}')
|
|
[ "$actual" = "$LIBSECCOMP_SRC_SHA256" ] || {
|
|
echo "!! libseccomp checksum mismatch (expected $LIBSECCOMP_SRC_SHA256, got $actual)" >&2
|
|
exit 1
|
|
}
|
|
mkdir -p "$d/src" && tar -xf "$d/src.tar.gz" -C "$d/src" --strip-components=1
|
|
( cd "$d/src" && ./autogen.sh && ./configure --prefix=/usr && make -j"$(nproc)" && make install )
|
|
else
|
|
echo "==> libseccomp already present, skipping bootstrap build"
|
|
fi
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 4. yajl — not part of stock Slackware, build from source if missing.
|
|
# -----------------------------------------------------------------------------
|
|
if ! pkg-config --exists yajl 2>/dev/null; then
|
|
echo "==> yajl not found, building v$YAJL_VERSION from source"
|
|
d="$WORK/yajl"
|
|
mkdir -p "$d"
|
|
curl -fL --retry 3 -o "$d/src.tar.gz" "$YAJL_SRC_URL"
|
|
actual=$(sha256sum "$d/src.tar.gz" | awk '{print $1}')
|
|
[ "$actual" = "$YAJL_SRC_SHA256" ] || {
|
|
echo "!! yajl checksum mismatch (expected $YAJL_SRC_SHA256, got $actual)" >&2
|
|
exit 1
|
|
}
|
|
mkdir -p "$d/src" && tar -xf "$d/src.tar.gz" -C "$d/src" --strip-components=1
|
|
# yajl's ./configure is a thin wrapper around CMake (not a cmake-free
|
|
# autoconf script, despite its name) — cmake must already be on PATH,
|
|
# see the slackpkg install list in step 0 above.
|
|
( cd "$d/src" && ./configure -p /usr && make -C build install )
|
|
ldconfig 2>/dev/null || true
|
|
else
|
|
echo "==> yajl already present, skipping bootstrap build"
|
|
fi
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 5. Go toolchain (podman) — official upstream tarball.
|
|
# -----------------------------------------------------------------------------
|
|
if ! command -v go > /dev/null 2>&1; then
|
|
echo "==> Go not found, installing $GO_VERSION"
|
|
curl -fL --retry 3 -o "$WORK/go.tar.gz" "$GO_SRC_URL"
|
|
actual=$(sha256sum "$WORK/go.tar.gz" | awk '{print $1}')
|
|
[ "$actual" = "$GO_SRC_SHA256" ] || {
|
|
echo "!! Go toolchain checksum mismatch (expected $GO_SRC_SHA256, got $actual)" >&2
|
|
exit 1
|
|
}
|
|
rm -rf /usr/local/go
|
|
tar -C /usr/local -xf "$WORK/go.tar.gz"
|
|
export PATH="/usr/local/go/bin:$PATH"
|
|
# Persist PATH for subsequent steps in the same GitHub Actions job.
|
|
if [ -n "${GITHUB_PATH:-}" ]; then
|
|
echo "/usr/local/go/bin" >> "$GITHUB_PATH"
|
|
fi
|
|
else
|
|
echo "==> Go already present: $(go version)"
|
|
fi
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 6. Rust toolchain (netavark, aardvark-dns) — via rustup.
|
|
# -----------------------------------------------------------------------------
|
|
if ! command -v cargo > /dev/null 2>&1; then
|
|
echo "==> Rust/cargo not found, installing via rustup ($RUST_CHANNEL channel)"
|
|
curl -fL --retry 3 --proto '=https' --tlsv1.2 -sSf "$RUSTUP_INIT_URL" \
|
|
| sh -s -- -y --default-toolchain "$RUST_CHANNEL" --profile minimal
|
|
# shellcheck source=/dev/null
|
|
. "$HOME/.cargo/env"
|
|
if [ -n "${GITHUB_PATH:-}" ]; then
|
|
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
|
fi
|
|
else
|
|
echo "==> Rust already present: $(cargo --version)"
|
|
fi
|
|
|
|
echo
|
|
echo "==> Build environment ready."
|