| @@ -3,6 +3,13 @@ |
| 3 | 3 | # build/vectrum-code plain binary |
| 4 | 4 | # build/Vectrum_Code-<version>-<arch>.AppImage |
| 5 | 5 | # |
| 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 | + # |
| 6 | 13 | # appimagetool is used from $PATH if present, otherwise downloaded once into |
| 7 | 14 | # build/.tools. Set APPIMAGETOOL=/path/to/appimagetool to use a specific one. |
| 8 | 15 | # |
| @@ -13,6 +20,8 @@ |
| 13 | 20 | # commit with the version, push the tag, and upload the |
| 14 | 21 | # AppImage, the binary and SHA256SUMS (the first upload |
| 15 | 22 | # 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 |
| 16 | 25 | # -h, --help show this |
| 17 | 26 | # |
| 18 | 27 | # 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' "$*"; } |
| 26 | 35 | die() { printf '\033[1;31mxx\033[0m %s\n' "$*" >&2; exit 1; } |
| 27 | 36 | |
| 28 | 37 | RELEASE=0 |
| 38 | + NATIVE=0 |
| 29 | 39 | NEW_VERSION="" |
| 30 | 40 | while (( $# )); do |
| 31 | 41 | case "$1" in |
| 32 | 42 | -r|--release) RELEASE=1 ;; |
| 43 | + --native) NATIVE=1 ;; |
| 33 | 44 | -v|--version) |
| 34 | 45 | [[ $# -ge 2 ]] || die "$1 needs a version, like $1 0.1.2" |
| 35 | 46 | NEW_VERSION="$2" |
| @@ -65,7 +76,22 @@ check_tag() { |
| 65 | 76 | done |
| 66 | 77 | } |
| 67 | 78 | |
| 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 | + |
| 69 | 95 | if (( RELEASE )); then |
| 70 | 96 | SERVER="${VECTRUM_URL:-https://vectrum.cc}" |
| 71 | 97 | SERVER="${SERVER%/}" |
| @@ -103,13 +129,53 @@ if (( RELEASE )); then |
| 103 | 129 | fi |
| 104 | 130 | |
| 105 | 131 | # ── 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')" |
| 111 | 132 | 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 | + |
| 112 | 170 | 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 |
| 113 | 179 | log "Binary: build/$NAME" |
| 114 | 180 | |
| 115 | 181 | # ── 2. AppDir ──────────────────────────────────────────────────────────────── |