Files
dragonx/build.sh
DanS d05302d450 build: stamp container builds with the real version instead of "-unk"
.dockerignore excludes .git, so util/genbuild.sh finds no repository inside
the container and emits "// No build information available", which
clientversion.cpp renders as the "-unk" suffix. Every binary produced by
./build.sh --linux-compat therefore self-reports "v1.2.0-unk" and cannot be
traced to a commit -- including release artifacts, since this build path is
part of the v1.2.0 tag.

Pre-generating src/obj/build.h does not survive (genbuild rewrites it when the
content differs), and simply un-ignoring .git does not help a linked worktree,
whose .git is a file pointing outside the build context.

So build.sh computes the version on the host, mirroring genbuild.sh rule for
rule -- the nearest tag only when HEAD is that tag and the tree is clean,
otherwise v<VERSION>-<short sha> with a -dirty suffix -- and passes it through
a BUILD_DESC build-arg that Dockerfile.compat exports as DRAGONX_BUILD_DESC.
genbuild.sh honours that variable when set and is otherwise untouched; with
git metadata present it emits a byte-identical build.h.

Every added git call is guarded with || true because build.sh runs under
set -eu -o pipefail: a source tarball, a host without git, or a branch whose
only reachable tags are lightweight (v1.0.1-v1.0.3 are lightweight; v1.1.0 is
the first annotated one) would otherwise abort the build with no diagnostic.
Those cases now degrade to the previous "-unk" behaviour with a warning.

A direct "docker build -f Dockerfile.compat" passes no BUILD_DESC and still
produces -unk; the Dockerfile now says so loudly rather than silently.
2026-08-29 01:39:24 +02:00

263 lines
10 KiB
Bash
Executable File

#!/usr/bin/env bash
# Copyright (c) 2016-2024 The Hush developers
# Copyright (c) 2024-2026 The DragonX developers
# Distributed under the GPLv3 software license, see the accompanying
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
set -eu -o pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RELEASE_DIR="$SCRIPT_DIR/release"
# Derive the release version from configure.ac instead of hardcoding it here.
# A stale literal names the release directories after the wrong version while the
# binaries inside report the real one: this said 1.0.3 while the tree was already
# 1.1.0, so `./build.sh --all-release` would have produced
# release/dragonx-1.0.3-<platform>/ full of binaries announcing 1.1.0.
# Mirrors configure.ac's _CLIENT_VERSION_SUFFIX m4 exactly:
# build < 25 -> beta(build+1) build < 50 -> rc(build-24)
# build == 50 -> plain release build > 50 -> point release (build-50)
_acdef() { sed -n "s/^define(_CLIENT_VERSION_$1, *\([0-9]\{1,\}\))/\1/p" "$SCRIPT_DIR/configure.ac"; }
_V_MAJOR="$(_acdef MAJOR)"
_V_MINOR="$(_acdef MINOR)"
_V_REVISION="$(_acdef REVISION)"
_V_BUILD="$(_acdef BUILD)"
if [ -z "$_V_MAJOR" ] || [ -z "$_V_MINOR" ] || [ -z "$_V_REVISION" ] || [ -z "$_V_BUILD" ]; then
echo "ERROR: could not read the version from $SCRIPT_DIR/configure.ac" >&2
echo " refusing to build a release whose directory name would be wrong." >&2
exit 1
fi
if [ "$_V_BUILD" -lt 25 ]; then _V_SUFFIX="$_V_REVISION-beta$((_V_BUILD + 1))"
elif [ "$_V_BUILD" -lt 50 ]; then _V_SUFFIX="$_V_REVISION-rc$((_V_BUILD - 24))"
elif [ "$_V_BUILD" -eq 50 ]; then _V_SUFFIX="$_V_REVISION"
else _V_SUFFIX="$_V_REVISION-$((_V_BUILD - 50))"
fi
VERSION="$_V_MAJOR.$_V_MINOR.$_V_SUFFIX"
# Parse release flags
BUILD_LINUX_RELEASE=0
BUILD_WIN_RELEASE=0
BUILD_MAC_RELEASE=0
BUILD_LINUX_COMPAT=0
REMAINING_ARGS=()
for arg in "$@"; do
case "$arg" in
--linux-release)
BUILD_LINUX_RELEASE=1
;;
--linux-compat)
BUILD_LINUX_COMPAT=1
;;
--win-release)
BUILD_WIN_RELEASE=1
;;
--mac-release)
BUILD_MAC_RELEASE=1
;;
--all-release)
BUILD_LINUX_RELEASE=1
BUILD_WIN_RELEASE=1
BUILD_MAC_RELEASE=1
;;
*)
REMAINING_ARGS+=("$arg")
;;
esac
done
# Clean artifacts that may conflict between platform builds
clean_for_platform() {
local platform="$1"
echo "Cleaning build artifacts for $platform build..."
# Use make clean if Makefile exists (safer than manual deletion)
if [ -f src/Makefile ]; then
make -C src clean 2>/dev/null || true
fi
# Remove final binaries
if [ -d src ]; then
rm -f src/dragonxd src/dragonx-cli src/dragonx-tx 2>/dev/null || true
rm -f src/dragonxd.exe src/dragonx-cli.exe src/dragonx-tx.exe 2>/dev/null || true
rm -f src/hushd src/hush-cli src/hush-tx 2>/dev/null || true
rm -f src/hushd.exe src/hush-cli.exe src/hush-tx.exe 2>/dev/null || true
fi
# Clean RandomX build for cross-platform compatibility
rm -rf src/RandomX/build 2>/dev/null || true
# Clean cryptoconditions
rm -rf src/cc/*.o src/cc/*.a 2>/dev/null || true
# Clean config cache (forces reconfigure for cross-platform)
rm -f config.status config.log 2>/dev/null || true
echo "Clean complete for $platform"
}
# Package release for a platform
package_release() {
local platform="$1"
local release_subdir="$RELEASE_DIR/dragonx-$VERSION-$platform"
echo "Packaging release for $platform..."
mkdir -p "$release_subdir"
# Copy bootstrap script (platform-appropriate)
if [ "$platform" = "win64" ]; then
cp "$SCRIPT_DIR/util/bootstrap-dragonx.bat" "$release_subdir/"
else
cp "$SCRIPT_DIR/util/bootstrap-dragonx.sh" "$release_subdir/"
fi
# Copy common files
cp "$SCRIPT_DIR/contrib/asmap/asmap.dat" "$release_subdir/" 2>/dev/null || true
cp "$SCRIPT_DIR/sapling-output.params" "$release_subdir/" 2>/dev/null || true
cp "$SCRIPT_DIR/sapling-spend.params" "$release_subdir/" 2>/dev/null || true
case "$platform" in
linux-amd64)
cp "$SCRIPT_DIR/src/dragonxd" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-cli" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-tx" "$release_subdir/"
strip "$release_subdir/dragonxd" "$release_subdir/dragonx-cli" "$release_subdir/dragonx-tx"
;;
win64)
cp "$SCRIPT_DIR/src/dragonxd.exe" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-cli.exe" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-tx.exe" "$release_subdir/"
x86_64-w64-mingw32-strip "$release_subdir/"*.exe 2>/dev/null || strip "$release_subdir/"*.exe 2>/dev/null || true
;;
macos)
cp "$SCRIPT_DIR/src/dragonxd" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-cli" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-tx" "$release_subdir/"
strip "$release_subdir/dragonxd" "$release_subdir/dragonx-cli" "$release_subdir/dragonx-tx" 2>/dev/null || true
;;
esac
echo "Release packaged: $release_subdir"
ls -la "$release_subdir"
}
# Handle release builds
if [ $BUILD_LINUX_COMPAT -eq 1 ] || [ $BUILD_LINUX_RELEASE -eq 1 ] || [ $BUILD_WIN_RELEASE -eq 1 ] || [ $BUILD_MAC_RELEASE -eq 1 ]; then
mkdir -p "$RELEASE_DIR"
if [ $BUILD_LINUX_COMPAT -eq 1 ]; then
echo "=== Building Linux compat release (Ubuntu 20.04 via Docker) ==="
if ! command -v docker &>/dev/null; then
echo "Error: docker is required for --linux-compat builds"
exit 1
fi
# Use sudo for docker if the user isn't in the docker group
DOCKER_CMD="docker"
if ! docker info &>/dev/null 2>&1; then
echo "Note: Using sudo for docker (add yourself to the docker group to avoid this)"
DOCKER_CMD="sudo docker"
fi
DOCKER_IMAGE="dragonx-compat-builder"
COMPAT_PLATFORM="linux-amd64-ubuntu2004"
COMPAT_RELEASE_DIR="$RELEASE_DIR/dragonx-$VERSION-$COMPAT_PLATFORM"
echo "Building Docker image (Ubuntu 20.04 base)..."
# .dockerignore excludes .git, so genbuild.sh inside the container cannot
# derive the version and would stamp the binaries "-unk". Compute it on the
# host, mirroring util/genbuild.sh exactly, and pass it in via --build-arg.
# NB: build.sh runs under `set -eu -o pipefail`, so every git call here must be
# non-fatal -- a source tarball, a machine without git, or a branch whose only
# reachable tags are lightweight (v1.0.1-v1.0.3) would otherwise abort the build.
git diff >/dev/null 2>&1 || true # refresh index: touched-but-unmodified are not dirty
COMPAT_BUILD_DESC=""
COMPAT_RAWDESC=$(git describe --abbrev=0 2>/dev/null || true)
if [ -n "$COMPAT_RAWDESC" ] \
&& [ "$(git rev-parse HEAD 2>/dev/null)" = "$(git rev-list -1 "$COMPAT_RAWDESC" 2>/dev/null)" ] \
&& git diff-index --quiet HEAD -- 2>/dev/null; then
COMPAT_BUILD_DESC="$COMPAT_RAWDESC"
else
COMPAT_SUFFIX=$(git rev-parse --short HEAD 2>/dev/null || true)
if [ -n "$COMPAT_SUFFIX" ]; then
git diff-index --quiet HEAD -- 2>/dev/null || COMPAT_SUFFIX="$COMPAT_SUFFIX-dirty"
COMPAT_BUILD_DESC="v$VERSION-$COMPAT_SUFFIX"
fi
fi
if [ -n "$COMPAT_BUILD_DESC" ]; then
echo "Stamping container build as: $COMPAT_BUILD_DESC"
else
echo "Warning: no usable git metadata; container binaries will be stamped -unk"
fi
$DOCKER_CMD build -f Dockerfile.compat \
--build-arg BUILD_DESC="$COMPAT_BUILD_DESC" \
-t "$DOCKER_IMAGE" .
echo "Extracting binaries from Docker image..."
CONTAINER_ID=$($DOCKER_CMD create "$DOCKER_IMAGE")
mkdir -p "$COMPAT_RELEASE_DIR"
for bin in dragonxd dragonx-cli dragonx-tx; do
$DOCKER_CMD cp "$CONTAINER_ID:/build/src/$bin" "$COMPAT_RELEASE_DIR/$bin"
done
$DOCKER_CMD rm "$CONTAINER_ID" >/dev/null
# Fix ownership (docker cp creates root-owned files)
# Binaries are already stripped inside the Docker container
if [ "$(stat -c '%U' "$COMPAT_RELEASE_DIR/dragonxd")" = "root" ]; then
sudo chown "$(id -u):$(id -g)" "$COMPAT_RELEASE_DIR"/dragonx*
fi
# Copy common files
cp "$SCRIPT_DIR/util/bootstrap-dragonx.sh" "$COMPAT_RELEASE_DIR/"
cp "$SCRIPT_DIR/contrib/asmap/asmap.dat" "$COMPAT_RELEASE_DIR/" 2>/dev/null || true
cp "$SCRIPT_DIR/sapling-output.params" "$COMPAT_RELEASE_DIR/" 2>/dev/null || true
cp "$SCRIPT_DIR/sapling-spend.params" "$COMPAT_RELEASE_DIR/" 2>/dev/null || true
echo "Compat release packaged: $COMPAT_RELEASE_DIR"
ls -la "$COMPAT_RELEASE_DIR"
# Show glibc version requirement
echo ""
echo "Binary compatibility info:"
objdump -T "$COMPAT_RELEASE_DIR/dragonxd" | grep -oP 'GLIBC_\d+\.\d+' | sort -uV | tail -1 && echo "(max GLIBC version required)"
fi
if [ $BUILD_LINUX_RELEASE -eq 1 ]; then
echo "=== Building Linux release ==="
clean_for_platform linux
./util/build.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
package_release linux-amd64
fi
if [ $BUILD_WIN_RELEASE -eq 1 ]; then
echo "=== Building Windows release ==="
clean_for_platform windows
./util/build-win.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
package_release win64
fi
if [ $BUILD_MAC_RELEASE -eq 1 ]; then
echo "=== Building macOS release ==="
clean_for_platform macos
./util/build-mac.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
package_release macos
fi
echo ""
echo "=== Release builds complete ==="
ls -la "$RELEASE_DIR"/
exit 0
fi
# Standard build (auto-detect OS)
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
./util/build.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
elif [[ "$OSTYPE" == "darwin"* ]]; then
./util/build-mac.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
elif [[ "$OSTYPE" == "msys"* ]]; then
./util/build-win.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
else
echo "Unable to detect your OS. What are you using?"
fi