From f893f6af7d36a5409fd804e81a34fd895cfefedf Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Wed, 28 Oct 2026 15:35:40 -0400 Subject: [PATCH] Honor CARGO_BUILD_TARGET in FreeBSD packaging for aarch64 release builds (#1507) * Honor CARGO_BUILD_TARGET in FreeBSD packaging for aarch64 release builds package.sh took the arch from uname -m and read binaries from target/release, so a cross-built aarch64 target would be packaged as the host arch from the wrong directory. Pass --target, read target//release, and name the archive from the target triple when CARGO_BUILD_TARGET is set. Skip the --version smoke run for cross builds, since the binary cannot run on the host. * Resolve host-tuple and reject unsupported targets in FreeBSD packaging Resolve CARGO_BUILD_TARGET=host-tuple to the real host triple before it is used in the target directory path. Accept only x86_64-unknown-freebsd and aarch64-unknown-freebsd when it is set, and fail with an error for anything else instead of mapping unknown targets to x86_64. * Validate staged FreeBSD binaries before packaging Check that deckcraft and deckcraft-cli are 64-bit little-endian FreeBSD ELF files for the selected arch before the archive is created, so placeholder, wrong-arch or non-FreeBSD binaries fail instead of being packaged. Applies to --skip-build and full builds. --- packaging/freebsd/package.sh | 46 +++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/packaging/freebsd/package.sh b/packaging/freebsd/package.sh index 80f3cf33..deffe19e 100755 --- a/packaging/freebsd/package.sh +++ b/packaging/freebsd/package.sh @@ -14,17 +14,47 @@ set -euo pipefail LINUX="$ROOT/packaging/linux" APP_ID=ai.storyteller.deckcraft -if [[ "${1:-}" != "--skip-build" ]]; then - (cd "$ROOT" && cargo build --release --locked -p deckcraft -p deckcraft-cli) +TARGET_ARGS=() +BIN="$CARGO_TARGET_DIR/release" +if [[ -n "${CARGO_BUILD_TARGET:-}" ]]; then + # host-tuple means the build host; resolve it so the target dir path is a real triple. + if [[ "$CARGO_BUILD_TARGET" == host-tuple ]]; then + CARGO_BUILD_TARGET="$(rustc -vV | sed -n 's/^host: //p')" + fi + # The target triple, not the build host's uname, names the arch of a cross build. + case "$CARGO_BUILD_TARGET" in + x86_64-unknown-freebsd) ARCH=x86_64 ;; + aarch64-unknown-freebsd) ARCH=aarch64 ;; + *) echo "error: unsupported CARGO_BUILD_TARGET '$CARGO_BUILD_TARGET' (expected x86_64-unknown-freebsd or aarch64-unknown-freebsd)" >&2; exit 1 ;; + esac + TARGET_ARGS=(--target "$CARGO_BUILD_TARGET") + BIN="$CARGO_TARGET_DIR/$CARGO_BUILD_TARGET/release" +else + ARCH="$(uname -m)" + case "$ARCH" in + amd64) ARCH=x86_64 ;; + arm64) ARCH=aarch64 ;; + *) ;; + esac fi -ARCH="$(uname -m)" +if [[ "${1:-}" != "--skip-build" ]]; then + (cd "$ROOT" && cargo build --release --locked "${TARGET_ARGS[@]}" -p deckcraft -p deckcraft-cli) +fi + +# Refuse placeholder, wrong-arch or non-FreeBSD binaries (also with --skip-build). Bytes: ELF magic, +# 64-bit little-endian, OSABI SYSV or FreeBSD, e_machine. case "$ARCH" in - amd64) ARCH=x86_64 ;; - arm64) ARCH=aarch64 ;; - *) ;; + x86_64) MACHINE=" 3e 00" ;; + aarch64) MACHINE=" b7 00" ;; + *) echo "error: no ELF machine check for arch '$ARCH'" >&2; exit 1 ;; esac -BIN="$CARGO_TARGET_DIR/release" +for f in "$BIN/deckcraft" "$BIN/deckcraft-cli"; do + [[ "$(od -An -tx1 -N6 "$f" 2>/dev/null)" == " 7f 45 4c 46 02 01" ]] || { echo "error: $f is not a 64-bit little-endian ELF" >&2; exit 1; } + [[ "$(od -An -tx1 -j7 -N1 "$f")" =~ ^\ (00|09)$ ]] || { echo "error: $f is not a FreeBSD ELF (OSABI)" >&2; exit 1; } + [[ "$(od -An -tx1 -j18 -N2 "$f")" == "$MACHINE" ]] || { echo "error: $f is not an ELF for $ARCH" >&2; exit 1; } +done + NAME="deckcraft-$VERSION-freebsd-$ARCH" WORK="$CARGO_TARGET_DIR/freebsd-package" STAGE="$WORK/$NAME" @@ -41,6 +71,6 @@ cp -R "$ROOT/assets/app-icon/hicolor" "$STAGE/share/icons/" copy_docs "$STAGE/share/doc/deckcraft" tar -C "$WORK" -czf "$DIST/$NAME.tar.gz" "$NAME" -"$STAGE/bin/deckcraft-cli" --version +if [[ -z "${CARGO_BUILD_TARGET:-}" || "$CARGO_BUILD_TARGET" == "$(rustc -vV | sed -n 's/^host: //p')" ]]; then "$STAGE/bin/deckcraft-cli" --version; fi # a cross-built binary cannot run on the build host echo "wrote $DIST/$NAME.tar.gz" ls -lh "$DIST/$NAME.tar.gz"