Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 271 additions & 0 deletions Build-Scripts/build-common.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
# Shared helpers for out-of-tree, per-platform Verium builds.
# Each platform uses its own:
# build/<platform>/ configure + object files
# depends/<host-triplet>/ cached dependency toolchain
# out-<platform>/ binaries
# release-<platform>/ stripped binaries (where applicable)
#
# Never configure at the repo root — that pollutes src/ and breaks cross-compiles.

build_common_root() {
cd "$(dirname "${BASH_SOURCE[0]}")/.."
BUILD_COMMON_ROOT="$(pwd)"
}

# Remove accidental in-tree configure/build artifacts (not platform build dirs).
clean_root_configure_artifacts() {
local root="${1:-$BUILD_COMMON_ROOT}"
cd "$root"

if [ -f config.status ] || [ -f Makefile ]; then
echo "=== Cleaning stale in-tree configure at repo root ==="
rm -f config.status config.log Makefile libtool
rm -rf src/config/bitcoin-config.h src/config/stamp-h1
find src -name '*.o' -delete
find src -name '*.a' -delete
find src -name '*.lo' -delete
find src -name '.deps' -type d -prune -exec rm -rf {} + 2>/dev/null || true
fi

# Subproject configure leakage from old in-tree builds
rm -rf src/univalue/config.* src/univalue/Makefile src/univalue/libtool src/univalue/.libs
rm -rf src/secp256k1/config.* src/secp256k1/Makefile src/secp256k1/libtool src/secp256k1/.libs
rm -f src/secp256k1/src/libsecp256k1-config.h
}

ensure_autogen() {
local root="${1:-$BUILD_COMMON_ROOT}"
cd "$root"
if [ ! -x configure ]; then
./autogen.sh
fi
}

# Source shared/depends-preseed helpers (env + depends-cache.sh).
source_shared_preseed_helpers() {
local root="${1:-$BUILD_COMMON_ROOT}"
local cache_root=""

if [ -n "${SHARED_DEPENDS_PRESEED:-}" ] && [ -f "${SHARED_DEPENDS_PRESEED}/depends-cache.sh" ]; then
cache_root="${SHARED_DEPENDS_PRESEED}"
elif [ -d "${root}/../shared/depends-preseed" ]; then
cache_root="$(cd "${root}/../shared/depends-preseed" && pwd)"
fi

if [ -z "$cache_root" ] || [ ! -f "${cache_root}/depends-cache.sh" ]; then
echo "ERROR: shared depends preseed not found at ${root}/../shared/depends-preseed" >&2
echo " Populate it with shared/depends-preseed/preseed-depends.sh" >&2
return 1
fi

if [ -f "${cache_root}/env.sh" ]; then
# shellcheck source=/dev/null
source "${cache_root}/env.sh"
fi
export DEPENDS_PRESEED_ROOT="${SHARED_DEPENDS_PRESEED:-$cache_root}"
export SHARED_DEPENDS_PRESEED="${SHARED_DEPENDS_PRESEED:-$cache_root}"
# shellcheck source=/dev/null
source "${cache_root}/depends-cache.sh"
}

ensure_depends() {
local host_triplet="$1"
local root="${2:-$BUILD_COMMON_ROOT}"
local extra_make_args="${3:-}"
cd "$root"

source_shared_preseed_helpers "$root" || exit 1
ensure_depends_with_shared_preseed "$host_triplet" "$root" "$extra_make_args" 4
}

# Docker: always mount CodeRepo/shared/depends-preseed at /shared/depends-preseed.
docker_shared_preseed_mount_args() {
local root="${1:-$BUILD_COMMON_ROOT}"
local shared
source_shared_preseed_helpers "$root" || exit 1
shared="$(default_shared_preseed_for_project "$root")" || exit 1
printf '%s\n' "-v" "${shared}:${DOCKER_SHARED_DEPENDS_PRESEED:-/shared/depends-preseed}" \
"-e" "SHARED_DEPENDS_PRESEED=${DOCKER_SHARED_DEPENDS_PRESEED:-/shared/depends-preseed}"
}

configure_platform_build() {
local build_dir="$1"
local host_triplet="$2"
local configure_extra="${3:-}"
local root="${4:-$BUILD_COMMON_ROOT}"
cd "$root"
mkdir -p "$build_dir"
cd "$build_dir"

export CONFIG_SITE="${root}/depends/${host_triplet}/share/config.site"
local dep="${root}/depends/${host_triplet}"

if [ -f config.status ]; then
echo "=== Reusing existing ${build_dir} (incremental) ==="
return 0
fi

echo "=== Configuring ${build_dir} for ${host_triplet} ==="
rm -f config.cache
# shellcheck disable=SC2086
../../configure --host="$host_triplet" --prefix="$dep" --with-gui=qt5 \
--with-qt-bindir="$dep/native/bin" --with-qt-incdir="$dep/include" --with-qt-libdir="$dep/lib" \
--disable-bench --disable-tests --enable-reduce-exports \
$configure_extra
}

ensure_secp256k1_gen_context() {
local build_dir="$1"
local root="${2:-$BUILD_COMMON_ROOT}"
cd "${root}/${build_dir}/src/secp256k1"
if [ -x gen_context ]; then
return 0
fi
echo "=== Building native gen_context for ${build_dir} ==="
gcc-9 -I../../../../src/secp256k1/src -I../../../../src/secp256k1 \
-c ../../../../src/secp256k1/src/gen_context.c -o gen_context.o
gcc-9 gen_context.o -o gen_context
}

platform_make() {
local build_dir="$1"
local root="${2:-$BUILD_COMMON_ROOT}"
local jobs="${3:-4}"
cd "${root}/${build_dir}"
make -j"$jobs" -C src/univalue
make -j"$jobs"
}

prepare_output_dirs() {
local root="${1:-$BUILD_COMMON_ROOT}"
local out_dir="$2"
local release_dir="${3:-}"
mkdir -p "${root}/${out_dir}"
if [ -n "$release_dir" ]; then
mkdir -p "${root}/${release_dir}"
fi
}

# --- Windows Developer Edition (debug machine) --------------------------------

WINDOWS_DEV_HOST_TRIPLET="${WINDOWS_DEV_HOST_TRIPLET:-x86_64-w64-mingw32}"
WINDOWS_DEV_BUILD_DIR="${WINDOWS_DEV_BUILD_DIR:-build/windows-dev}"
WINDOWS_DEV_OUT_DIR="${WINDOWS_DEV_OUT_DIR:-out-windows-dev}"
WINDOWS_DEV_RELEASE_DIR="${WINDOWS_DEV_RELEASE_DIR:-release-windows-dev}"

require_dev_helper_enabled() {
local root="${1:-$BUILD_COMMON_ROOT}"
if ! grep -q '^#define ENABLE_DEV_HELPER_WINDOW 1' "${root}/src/util/devhelperconfig.h" 2>/dev/null; then
echo "ERROR: Developer Edition requires ENABLE_DEV_HELPER_WINDOW 1 in src/util/devhelperconfig.h" >&2
echo " Set it to 1 on this debug machine, then re-run." >&2
echo " For holder/release builds use Build-Scripts/build-windows-docker.sh with the flag at 0." >&2
exit 1
fi
}

ensure_windows_cross_toolchain() {
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y build-essential automake libtool pkg-config python3 \
g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 \
curl zip unzip gcc-9 g++-9 nsis git

update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 100
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 100
update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix
update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix

export RC="${WINDOWS_DEV_HOST_TRIPLET}-windres"
export WINDRES="${WINDOWS_DEV_HOST_TRIPLET}-windres"
}

patch_curl_mk_for_windows_cross() {
local root="${1:-$BUILD_COMMON_ROOT}"
local f="${root}/depends/packages/curl.mk"
if [ -f "$f" ] && ! grep -q 'CI: cross-compile opts' "$f"; then
cat >> "$f" <<'EOF'

# CI: cross-compile opts for Windows
$(package)_config_opts += --disable-debug --disable-curldebug --disable-ldap --disable-ldaps --without-libidn2 --without-libpsl --without-brotli --without-zstd --without-nghttp2 --without-ssh --without-libssh2 --without-rtmp --disable-smb
$(package)_config_opts_mingw32 += --with-winssl
$(package)_config_opts_mingw64 += --with-winssl
$(package)_conf_env += ac_cv_func_strerror_r=no ac_cv_strerror_r_char_p=no ac_cv_func_clock_gettime=no ac_cv_header_dlfcn_h=no ac_cv_have_decl_strerror_r=yes
EOF
fi
}

patch_time_cpp_for_windows_cross() {
local root="${1:-$BUILD_COMMON_ROOT}"
if [ -f "${root}/src/util/time.cpp" ] && ! grep -q gmtime_r_compat "${root}/src/util/time.cpp"; then
{
echo '#ifdef _WIN32'
echo '#include <time.h>'
echo 'static inline struct tm* gmtime_r_compat(const time_t* t, struct tm* res){ return gmtime_s(res,t)==0 ? res : NULL; }'
echo '#define gmtime_r(t,r) gmtime_r_compat((t),(r))'
echo '#endif'
cat "${root}/src/util/time.cpp"
} > "${root}/src/util/time.cpp.tmp" && mv "${root}/src/util/time.cpp.tmp" "${root}/src/util/time.cpp"
fi
}

copy_windows_dev_binaries() {
local root="${1:-$BUILD_COMMON_ROOT}"
local build_dir="${2:-$WINDOWS_DEV_BUILD_DIR}"
local out_dir="${3:-$WINDOWS_DEV_OUT_DIR}"
local release_dir="${4:-$WINDOWS_DEV_RELEASE_DIR}"

prepare_output_dirs "$root" "$out_dir" "$release_dir"
cp -f "${root}/${build_dir}/src/"*.exe "${root}/${out_dir}/" 2>/dev/null || true
cp -f "${root}/${build_dir}/src/qt/"*.exe "${root}/${out_dir}/" 2>/dev/null || true
cp -f "${root}/${build_dir}/release/"*.exe "${root}/${release_dir}/" 2>/dev/null || true
}

clean_windows_dev_output_dir() {
local root="${1:-$BUILD_COMMON_ROOT}"
local out_dir="${2:-$WINDOWS_DEV_OUT_DIR}"
if [ -d "${root}/${out_dir}" ]; then
echo "=== Cleaning ${out_dir}/ before dev build ==="
rm -rf "${root}/${out_dir}"
fi
}

clean_windows_dev_build_dir() {
local root="${1:-$BUILD_COMMON_ROOT}"
local build_dir="${2:-$WINDOWS_DEV_BUILD_DIR}"
if [ -d "${root}/${build_dir}" ]; then
echo "=== Cleaning ${build_dir}/ before dev build ==="
rm -rf "${root}/${build_dir}"
fi
}

# Compile all Windows dev binaries and build the Developer Edition NSIS installer.
run_windows_dev_compile_and_package() {
local root="${1:-$BUILD_COMMON_ROOT}"
local host_triplet="${WINDOWS_DEV_HOST_TRIPLET}"
local build_dir="${WINDOWS_DEV_BUILD_DIR}"
local out_dir="${WINDOWS_DEV_OUT_DIR}"

require_dev_helper_enabled "$root"
clean_windows_dev_build_dir "$root" "$build_dir"
clean_windows_dev_output_dir "$root" "$out_dir"
ensure_windows_cross_toolchain
patch_curl_mk_for_windows_cross "$root"
patch_time_cpp_for_windows_cross "$root"

clean_root_configure_artifacts "$root"
ensure_depends "$host_triplet" "$root" "RC=\$RC WINDRES=\$WINDRES"
ensure_autogen "$root"
configure_platform_build "$build_dir" "$host_triplet" \
'--disable-shared --enable-static ac_cv_search_clock_gettime=no' "$root"
ensure_secp256k1_gen_context "$build_dir" "$root"
platform_make "$build_dir" "$root" 4

copy_windows_dev_binaries "$root" "$build_dir" "$out_dir" "$WINDOWS_DEV_RELEASE_DIR"

chmod +x "${root}/Build-Scripts/package-windows-dev-installer.sh"
"${root}/Build-Scripts/package-windows-dev-installer.sh" "$root"

echo "=== Windows Developer Edition recompile complete ==="
echo "Binaries + installer: ${root}/${out_dir}/"
ls -la "${root}/${out_dir}/"
}
96 changes: 34 additions & 62 deletions Build-Scripts/build-in-docker.sh
Original file line number Diff line number Diff line change
@@ -1,79 +1,51 @@
#!/bin/bash
# Run full Linux64 build inside ubuntu-22.04 container (matches GitHub Actions)
# Linux x64 native build (out-of-tree).
# build/linux64/ + depends/x86_64-pc-linux-gnu/ + out-linux64/
#
# Depends always sync from CodeRepo/shared/depends-preseed (see build-common.sh).
set -e
cd "$(dirname "$0")/.."
ROOT="$(pwd)"

# shellcheck source=build-common.sh
source Build-Scripts/build-common.sh
mapfile -t PRESEED_MOUNT < <(docker_shared_preseed_mount_args "$ROOT")

PLATFORM=linux64
HOST_TRIPLET=x86_64-pc-linux-gnu
BUILD_DIR="build/${PLATFORM}"
OUT_DIR="out-${PLATFORM}"

docker run --rm \
-v "$(pwd):/build" \
-v "$ROOT:/build" \
"${PRESEED_MOUNT[@]}" \
-w /build \
ubuntu:22.04 \
bash -c "
set -e
source Build-Scripts/build-common.sh
build_common_root

export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y gcc-9 g++-9 gcc-11 g++-11 build-essential automake libtool pkg-config python3 curl zip unzip ccache
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 100 \
--slave /usr/bin/g++ g++ /usr/bin/g++-9 \
--slave /usr/bin/gcov gcov /usr/bin/gcov-9 \
--slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-9 \
--slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-9 \
--slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-9
export CC=gcc-9 CXX=g++-9 HOST_TRIPLET=$HOST_TRIPLET
gcc --version
g++ --version

echo '=== Priming FreeType with GCC 11 ==='
make -C depends HOST=\$HOST_TRIPLET CC=gcc-11 CXX=g++-11 freetype -j\$(nproc)

echo '=== Building full depends ==='
make -C depends HOST=\$HOST_TRIPLET CC=gcc-9 CXX=g++-9 -j\$(nproc)
apt-get install -y build-essential automake libtool pkg-config python3 \
curl git bison ca-certificates gcc-9 g++-9

echo '=== Autogen ==='
./autogen.sh
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 100
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 100

echo '=== Configuring ==='
export CONFIG_SITE=\"\$(pwd)/depends/\$HOST_TRIPLET/share/config.site\"
DEP=\"\$(pwd)/depends/\$HOST_TRIPLET\"
export BOOST_CPPFLAGS=\"-I\$DEP/include\"
export BOOST_LDFLAGS=\"-L\$DEP/lib\"
export CPPFLAGS=\"\$BOOST_CPPFLAGS\"
export LDFLAGS=\"\$BOOST_LDFLAGS\"
bs=\"\$(ls \"\$DEP/lib\"/libboost_system*.a 2>/dev/null | head -n1 || true)\"
if [ -z \"\$bs\" ]; then echo 'ERROR: No libboost_system'; exit 1; fi
suf=\"\${bs##*/}\"; suf=\"\${suf#libboost_system}\"; suf=\"\${suf%.a}\"
export BOOST_LIB_SUFFIX=\"\$suf\"
export BOOST_THREAD_LIB_SUFFIX=\"\$suf\"
export LIBS=\"-pthread -lrt\"
CC=gcc-9 CXX=g++-9 ./configure --host=\$HOST_TRIPLET --prefix=\"\$DEP\" --with-gui=qt5 \\
--with-qt-bindir=\"\$DEP/native/bin\" --with-qt-incdir=\"\$DEP/include\" --with-qt-libdir=\"\$DEP/lib\" \\
--with-boost=\"\$DEP\" --with-boost-libdir=\"\$DEP/lib\" \\
--disable-bench --disable-tests --enable-reduce-exports --disable-shared --enable-static
clean_root_configure_artifacts /build
ensure_depends ${HOST_TRIPLET} /build
ensure_autogen /build
configure_platform_build ${BUILD_DIR} ${HOST_TRIPLET} '' /build
platform_make ${BUILD_DIR} /build 4

echo '=== Building ==='
make clean
make CC=\$CC CXX=\$CXX -j\$(nproc)
cd /build
prepare_output_dirs /build ${OUT_DIR}
cp -f ${BUILD_DIR}/src/veriumd ${BUILD_DIR}/src/verium-cli ${BUILD_DIR}/src/verium-tx \
${BUILD_DIR}/src/verium-wallet ${BUILD_DIR}/src/qt/verium-qt /build/${OUT_DIR}/
chown 1000:1000 /build/${OUT_DIR}/* 2>/dev/null || true

echo '=== Packaging ==='
V=\$(grep '^PACKAGE_VERSION' Makefile 2>/dev/null | sed 's/.*= *//' | tr -d ' ') || echo '1.3.5.2'
OUTDIR=\"out-linux\"
rm -rf \"\$OUTDIR\"
mkdir -p \"\$OUTDIR\"/{daemon,doc,manpages,share/applications,share/pixmaps,share/icons/hicolor/128x128/apps}
cp -f src/qt/verium-qt \"\$OUTDIR/\"
cp -f COPYING \"\$OUTDIR/\"
cp -f doc/README_windows.txt \"\$OUTDIR/readme.txt\"
cp -f src/veriumd src/verium-cli src/verium-tx src/verium-wallet \"\$OUTDIR/daemon/\" 2>/dev/null || true
cp -r doc \"\$OUTDIR/\"
rm -rf \"\$OUTDIR/doc/man\"
find \"\$OUTDIR/doc\" -name 'Makefile*' -delete 2>/dev/null || true
./contrib/release-tools/gather-manpages.sh \"\$OUTDIR/manpages\"
cp -f share/applications/verium-qt.desktop \"\$OUTDIR/share/applications/\"
cp -f share/pixmaps/verium-qt.png \"\$OUTDIR/share/pixmaps/\"
cp -f share/pixmaps/verium-qt.png \"\$OUTDIR/share/icons/hicolor/128x128/apps/\"
cp -f contrib/release-tools/INSTALL_LINUX.txt \"\$OUTDIR/\"
PKG=\"verium-\${V}-x86_64-pc-linux-gnu.tar.gz\"
tar -C \"\$OUTDIR\" -czf \"\$PKG\" .
sha256sum \"\$PKG\" > \"\${PKG}.SHA256SUMS\"
echo \"Built: \$PKG\"
ls -la \"\$PKG\" \"\${PKG}.SHA256SUMS\"
echo '=== Linux x64 build complete ==='
ls -la /build/${OUT_DIR}/
"
Loading