Vectrum
Sign In

build.sh: build in an Ubuntu 24.04 container again

The container build from t3/build-for-older-linux-distros never reached
master, so releases were linked against the host's glibc 2.44 and would not
start on Ubuntu 24.04 (2.39) or Fedora 44 (2.43). build.sh builds in the
Ubuntu 24.04 image by default again, next to -v and -r, and stops if the
binary needs a glibc newer than 2.39; --native keeps the host build. Docker
is used directly, through sudo when only root can reach it, or as $DOCKER,
and is checked before -v commits a version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JjohannSocommitted 1 parent 06f3e7acommitd78d175

Showing 2 changed files with 77 additions and 7 deletions.

+5−1README.mdView File
@@ -301,7 +301,11 @@ in its `scratch` folder.
301301
302302 ## Build and release
303303
304- `./build.sh` builds the release binary and an AppImage into `build/`. `-v 0.1.2` first sets the
304+ `./build.sh` builds the release binary and an AppImage into `build/`. It builds in an Ubuntu
305+ 24.04 container, so the binary needs only glibc 2.39 and runs on Ubuntu 24.04, Fedora 40,
306+ Debian 13 and newer; that needs Docker (directly, through `sudo`, or as `DOCKER="…"`), and
307+ the image, target dir and cargo cache are kept in `target/ubuntu-24.04`. `--native` builds with
308+ the host toolchain instead, for the host's glibc or newer. `-v 0.1.2` first sets the
305309 version (in `Cargo.toml` and `Cargo.lock`, committed as "Version 0.1.2"), and `--release` (or
306310 `-r`) publishes the build on Vectrum: it tags the commit with the version, pushes the tag, and
307311 uploads the AppImage, the binary and `SHA256SUMS`, which publishes the release. So
+72−6build.shView File
@@ -3,6 +3,13 @@
33 # build/vectrum-code plain binary
44 # build/Vectrum_Code-<version>-<arch>.AppImage
55 #
6+ # A binary only runs on the glibc it was linked against or a newer one, so by
7+ # default it is built in an Ubuntu 24.04 container and linked against glibc
8+ # 2.39: it runs on Ubuntu 24.04, Fedora 40, Debian 13 and anything newer. The
9+ # image is built once; its target dir and cargo cache stay in
10+ # target/ubuntu-24.04. Docker is used directly, or through sudo when only root
11+ # can reach it; set DOCKER="sudo docker" (or another command) to choose.
12+ #
613 # appimagetool is used from $PATH if present, otherwise downloaded once into
714 # build/.tools. Set APPIMAGETOOL=/path/to/appimagetool to use a specific one.
815 #
@@ -13,6 +20,8 @@
1320 # commit with the version, push the tag, and upload the
1421 # AppImage, the binary and SHA256SUMS (the first upload
1522 # publishes the release). Each release needs a new version.
23+ # --native build with the host toolchain instead of the container;
24+ # the binary then needs the host's glibc or newer
1625 # -h, --help show this
1726 #
1827 # So ./build.sh -v 0.1.2 -r makes and publishes version 0.1.2. Releasing reads:
@@ -26,10 +35,12 @@ log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
2635 die() { printf '\033[1;31mxx\033[0m %s\n' "$*" >&2; exit 1; }
2736
2837 RELEASE=0
38+ NATIVE=0
2939 NEW_VERSION=""
3040 while (( $# )); do
3141 case "$1" in
3242 -r|--release) RELEASE=1 ;;
43+ --native) NATIVE=1 ;;
3344 -v|--version)
3445 [[ $# -ge 2 ]] || die "$1 needs a version, like $1 0.1.2"
3546 NEW_VERSION="$2"
@@ -65,7 +76,22 @@ check_tag() {
6576 done
6677 }
6778
68- # ── 0. Version and release checks, before spending time on a build ───────────
79+ # ── 0. Version, release and Docker checks, before spending time on a build ───
80+ if (( ! NATIVE )); then
81+ if [[ -n "${DOCKER:-}" ]]; then
82+ read -ra DOCKER <<< "$DOCKER"
83+ elif docker info >/dev/null 2>&1; then
84+ DOCKER=(docker)
85+ elif sudo -n docker info >/dev/null 2>&1; then
86+ DOCKER=(sudo docker)
87+ else
88+ DOCKER=(docker)
89+ fi
90+ command -v "${DOCKER[0]}" >/dev/null || die "Docker is needed for this build (or use --native)"
91+ "${DOCKER[@]}" info >/dev/null 2>&1 ||
92+ die "Can't reach Docker as ${DOCKER[*]}: start it, join the docker group, set DOCKER=\"sudo docker\", or use --native"
93+ fi
94+
6995 if (( RELEASE )); then
7096 SERVER="${VECTRUM_URL:-https://vectrum.cc}"
7197 SERVER="${SERVER%/}"
@@ -103,13 +129,53 @@ if (( RELEASE )); then
103129 fi
104130
105131 # ── 1. Binary ────────────────────────────────────────────────────────────────
106- log "Building $NAME $VERSION (release, $ARCH)"
107- cargo build --release --manifest-path "$ROOT/Cargo.toml"
108-
109- TARGET_DIR="$(cargo metadata --format-version 1 --no-deps --manifest-path "$ROOT/Cargo.toml" |
110- sed -n 's/.*"target_directory":"\([^"]*\)".*/\1/p')"
111132 mkdir -p "$BUILD"
133+ if (( NATIVE )); then
134+ log "Building $NAME $VERSION (release, $ARCH, host toolchain)"
135+ cargo build --release --manifest-path "$ROOT/Cargo.toml"
136+
137+ TARGET_DIR="$(cargo metadata --format-version 1 --no-deps --manifest-path "$ROOT/Cargo.toml" |
138+ sed -n 's/.*"target_directory":"\([^"]*\)".*/\1/p')"
139+ else
140+ IMAGE="vectrum-code-build:ubuntu-24.04"
141+ GLIBC_MAX="2.39"
142+ TARGET_DIR="$ROOT/target/ubuntu-24.04"
143+
144+ log "Preparing the Ubuntu 24.04 build image"
145+ "${DOCKER[@]}" build --quiet -t "$IMAGE" - >/dev/null <<'EOF'
146+ FROM ubuntu:24.04
147+ RUN apt-get update \
148+ && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
149+ ca-certificates curl build-essential pkg-config clang libclang-dev cmake \
150+ libxcb1-dev libxkbcommon-dev libxkbcommon-x11-dev libwayland-dev \
151+ libfontconfig-dev libfreetype-dev libvulkan-dev \
152+ && rm -rf /var/lib/apt/lists/*
153+ ENV RUSTUP_HOME=/opt/rustup CARGO_HOME=/opt/cargo PATH=/opt/cargo/bin:$PATH
154+ RUN curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal --no-modify-path \
155+ && chmod -R a+rwX /opt/rustup /opt/cargo
156+ EOF
157+
158+ log "Building $NAME $VERSION (release, $ARCH, Ubuntu 24.04 / glibc $GLIBC_MAX)"
159+ mkdir -p "$TARGET_DIR/cargo-home"
160+ # Runs as the calling user so target/ and build/ stay theirs, even through sudo.
161+ "${DOCKER[@]}" run --rm --init \
162+ --user "$(id -u):$(id -g)" \
163+ -e HOME=/tmp \
164+ -e CARGO_HOME=/src/target/ubuntu-24.04/cargo-home \
165+ -e CARGO_TARGET_DIR=/src/target/ubuntu-24.04 \
166+ -v "$ROOT:/src" -w /src \
167+ "$IMAGE" cargo build --release --locked
168+ fi
169+
112170 install -m755 "$TARGET_DIR/release/$NAME" "$BUILD/$NAME"
171+
172+ if (( ! NATIVE )); then
173+ # Stop if anything still pulled in a glibc symbol newer than the container's.
174+ NEED="$(objdump -T "$BUILD/$NAME" | grep -o 'GLIBC_[0-9.]*' | sed 's/GLIBC_//' | sort -uV | tail -n1)"
175+ [[ "$(printf '%s\n%s\n' "$NEED" "$GLIBC_MAX" | sort -V | tail -n1)" == "$GLIBC_MAX" ]] ||
176+ die "build/$NAME needs glibc $NEED, more than Ubuntu 24.04's $GLIBC_MAX"
177+ log "Binary needs glibc $NEED or newer"
178+ fi
113179 log "Binary: build/$NAME"
114180
115181 # ── 2. AppDir ────────────────────────────────────────────────────────────────