mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-12 18:44:59 +01:00
The MacOS binaries are unsigned and therefore also unusable on MacOS. Indicate as such by naming the tarball "unsigned".
401 lines
16 KiB
Bash
Executable file
401 lines
16 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Copyright (c) 2019-2022 The Bitcoin Core developers
|
|
# Distributed under the MIT software license, see the accompanying
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
export LC_ALL=C
|
|
set -e -o pipefail
|
|
export TZ=UTC
|
|
|
|
# Although Guix _does_ set umask when building its own packages (in our case,
|
|
# this is all packages in manifest.scm), it does not set it for `guix
|
|
# shell`. It does make sense for at least `guix shell --container`
|
|
# to set umask, so if that change gets merged upstream and we bump the
|
|
# time-machine to a commit which includes the aforementioned change, we can
|
|
# remove this line.
|
|
#
|
|
# This line should be placed before any commands which creates files.
|
|
umask 0022
|
|
|
|
if [ -n "$V" ]; then
|
|
# Print both unexpanded (-v) and expanded (-x) forms of commands as they are
|
|
# read from this file.
|
|
set -vx
|
|
# Set VERBOSE for CMake-based builds
|
|
export VERBOSE="$V"
|
|
fi
|
|
|
|
# Check that required environment variables are set
|
|
cat << EOF
|
|
Required environment variables as seen inside the container:
|
|
DIST_ARCHIVE_BASE: ${DIST_ARCHIVE_BASE:?not set}
|
|
DISTNAME: ${DISTNAME:?not set}
|
|
HOST: ${HOST:?not set}
|
|
SOURCE_DATE_EPOCH: ${SOURCE_DATE_EPOCH:?not set}
|
|
JOBS: ${JOBS:?not set}
|
|
DISTSRC: ${DISTSRC:?not set}
|
|
OUTDIR: ${OUTDIR:?not set}
|
|
EOF
|
|
|
|
ACTUAL_OUTDIR="${OUTDIR}"
|
|
OUTDIR="${DISTSRC}/output"
|
|
|
|
#####################
|
|
# Environment Setup #
|
|
#####################
|
|
|
|
# The depends folder also serves as a base-prefix for depends packages for
|
|
# $HOSTs after successfully building.
|
|
BASEPREFIX="${PWD}/depends"
|
|
|
|
# Given a package name and an output name, return the path of that output in our
|
|
# current guix environment
|
|
store_path() {
|
|
grep --extended-regexp "/[^-]{32}-${1}-[^-]+${2:+-${2}}" "${GUIX_ENVIRONMENT}/manifest" \
|
|
| head --lines=1 \
|
|
| sed --expression='s|\x29*$||' \
|
|
--expression='s|^[[:space:]]*"||' \
|
|
--expression='s|"[[:space:]]*$||'
|
|
}
|
|
|
|
|
|
# Set environment variables to point the NATIVE toolchain to the right
|
|
# includes/libs
|
|
NATIVE_GCC="$(store_path gcc-toolchain)"
|
|
|
|
unset LIBRARY_PATH
|
|
unset CPATH
|
|
unset C_INCLUDE_PATH
|
|
unset CPLUS_INCLUDE_PATH
|
|
unset OBJC_INCLUDE_PATH
|
|
unset OBJCPLUS_INCLUDE_PATH
|
|
|
|
export C_INCLUDE_PATH="${NATIVE_GCC}/include"
|
|
export CPLUS_INCLUDE_PATH="${NATIVE_GCC}/include/c++:${NATIVE_GCC}/include"
|
|
|
|
case "$HOST" in
|
|
*darwin*) export LIBRARY_PATH="${NATIVE_GCC}/lib" ;; # Required for qt/qmake
|
|
*mingw*) export LIBRARY_PATH="${NATIVE_GCC}/lib" ;;
|
|
*)
|
|
NATIVE_GCC_STATIC="$(store_path gcc-toolchain static)"
|
|
export LIBRARY_PATH="${NATIVE_GCC}/lib:${NATIVE_GCC_STATIC}/lib"
|
|
;;
|
|
esac
|
|
|
|
# Set environment variables to point the CROSS toolchain to the right
|
|
# includes/libs for $HOST
|
|
case "$HOST" in
|
|
*mingw*)
|
|
# Determine output paths to use in CROSS_* environment variables
|
|
CROSS_GLIBC="$(store_path "mingw-w64-x86_64-winpthreads")"
|
|
CROSS_GCC="$(store_path "gcc-cross-${HOST}")"
|
|
CROSS_GCC_LIB_STORE="$(store_path "gcc-cross-${HOST}" lib)"
|
|
CROSS_GCC_LIBS=( "${CROSS_GCC_LIB_STORE}/lib/gcc/${HOST}"/* ) # This expands to an array of directories...
|
|
CROSS_GCC_LIB="${CROSS_GCC_LIBS[0]}" # ...we just want the first one (there should only be one)
|
|
|
|
# The search path ordering is generally:
|
|
# 1. gcc-related search paths
|
|
# 2. libc-related search paths
|
|
# 2. kernel-header-related search paths (not applicable to mingw-w64 hosts)
|
|
export CROSS_C_INCLUDE_PATH="${CROSS_GCC_LIB}/include:${CROSS_GCC_LIB}/include-fixed:${CROSS_GLIBC}/include"
|
|
export CROSS_CPLUS_INCLUDE_PATH="${CROSS_GCC}/include/c++:${CROSS_GCC}/include/c++/${HOST}:${CROSS_GCC}/include/c++/backward:${CROSS_C_INCLUDE_PATH}"
|
|
export CROSS_LIBRARY_PATH="${CROSS_GCC_LIB_STORE}/lib:${CROSS_GCC_LIB}:${CROSS_GLIBC}/lib"
|
|
;;
|
|
*darwin*)
|
|
# The CROSS toolchain for darwin uses the SDK and ignores environment variables.
|
|
# See depends/hosts/darwin.mk for more details.
|
|
;;
|
|
*linux*)
|
|
CROSS_GLIBC="$(store_path "glibc-cross-${HOST}")"
|
|
CROSS_GLIBC_STATIC="$(store_path "glibc-cross-${HOST}" static)"
|
|
CROSS_KERNEL="$(store_path "linux-libre-headers-cross-${HOST}")"
|
|
CROSS_GCC="$(store_path "gcc-cross-${HOST}")"
|
|
CROSS_GCC_LIB_STORE="$(store_path "gcc-cross-${HOST}" lib)"
|
|
CROSS_GCC_LIBS=( "${CROSS_GCC_LIB_STORE}/lib/gcc/${HOST}"/* ) # This expands to an array of directories...
|
|
CROSS_GCC_LIB="${CROSS_GCC_LIBS[0]}" # ...we just want the first one (there should only be one)
|
|
|
|
export CROSS_C_INCLUDE_PATH="${CROSS_GCC_LIB}/include:${CROSS_GCC_LIB}/include-fixed:${CROSS_GLIBC}/include:${CROSS_KERNEL}/include"
|
|
export CROSS_CPLUS_INCLUDE_PATH="${CROSS_GCC}/include/c++:${CROSS_GCC}/include/c++/${HOST}:${CROSS_GCC}/include/c++/backward:${CROSS_C_INCLUDE_PATH}"
|
|
export CROSS_LIBRARY_PATH="${CROSS_GCC_LIB_STORE}/lib:${CROSS_GCC_LIB}:${CROSS_GLIBC}/lib:${CROSS_GLIBC_STATIC}/lib"
|
|
;;
|
|
*)
|
|
exit 1 ;;
|
|
esac
|
|
|
|
# Sanity check CROSS_*_PATH directories
|
|
IFS=':' read -ra PATHS <<< "${CROSS_C_INCLUDE_PATH}:${CROSS_CPLUS_INCLUDE_PATH}:${CROSS_LIBRARY_PATH}"
|
|
for p in "${PATHS[@]}"; do
|
|
if [ -n "$p" ] && [ ! -d "$p" ]; then
|
|
echo "'$p' doesn't exist or isn't a directory... Aborting..."
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Disable Guix ld auto-rpath behavior
|
|
export GUIX_LD_WRAPPER_DISABLE_RPATH=yes
|
|
|
|
# Make /usr/bin if it doesn't exist
|
|
[ -e /usr/bin ] || mkdir -p /usr/bin
|
|
|
|
# Symlink file and env to a conventional path
|
|
[ -e /usr/bin/file ] || ln -s --no-dereference "$(command -v file)" /usr/bin/file
|
|
[ -e /usr/bin/env ] || ln -s --no-dereference "$(command -v env)" /usr/bin/env
|
|
|
|
# Determine the correct value for -Wl,--dynamic-linker for the current $HOST
|
|
case "$HOST" in
|
|
*linux*)
|
|
glibc_dynamic_linker=$(
|
|
case "$HOST" in
|
|
x86_64-linux-gnu) echo /lib64/ld-linux-x86-64.so.2 ;;
|
|
arm-linux-gnueabihf) echo /lib/ld-linux-armhf.so.3 ;;
|
|
aarch64-linux-gnu) echo /lib/ld-linux-aarch64.so.1 ;;
|
|
riscv64-linux-gnu) echo /lib/ld-linux-riscv64-lp64d.so.1 ;;
|
|
powerpc64-linux-gnu) echo /lib64/ld64.so.1;;
|
|
powerpc64le-linux-gnu) echo /lib64/ld64.so.2;;
|
|
*) exit 1 ;;
|
|
esac
|
|
)
|
|
;;
|
|
esac
|
|
|
|
# Environment variables for determinism
|
|
export TAR_OPTIONS="--owner=0 --group=0 --numeric-owner --mtime='@${SOURCE_DATE_EPOCH}' --sort=name"
|
|
export TZ="UTC"
|
|
|
|
####################
|
|
# Depends Building #
|
|
####################
|
|
|
|
# Build the depends tree, overriding variables that assume multilib gcc
|
|
make -C depends --jobs="$JOBS" HOST="$HOST" \
|
|
${V:+V=1} \
|
|
${SOURCES_PATH+SOURCES_PATH="$SOURCES_PATH"} \
|
|
${BASE_CACHE+BASE_CACHE="$BASE_CACHE"} \
|
|
${SDK_PATH+SDK_PATH="$SDK_PATH"} \
|
|
x86_64_linux_CC=x86_64-linux-gnu-gcc \
|
|
x86_64_linux_CXX=x86_64-linux-gnu-g++ \
|
|
x86_64_linux_AR=x86_64-linux-gnu-gcc-ar \
|
|
x86_64_linux_RANLIB=x86_64-linux-gnu-gcc-ranlib \
|
|
x86_64_linux_NM=x86_64-linux-gnu-gcc-nm \
|
|
x86_64_linux_STRIP=x86_64-linux-gnu-strip
|
|
|
|
case "$HOST" in
|
|
*darwin*)
|
|
# Unset now that Qt is built
|
|
unset C_INCLUDE_PATH
|
|
unset CPLUS_INCLUDE_PATH
|
|
unset LIBRARY_PATH
|
|
;;
|
|
esac
|
|
|
|
###########################
|
|
# Source Tarball Building #
|
|
###########################
|
|
|
|
GIT_ARCHIVE="${DIST_ARCHIVE_BASE}/${DISTNAME}.tar.gz"
|
|
|
|
# Create the source tarball if not already there
|
|
if [ ! -e "$GIT_ARCHIVE" ]; then
|
|
mkdir -p "$(dirname "$GIT_ARCHIVE")"
|
|
git archive --prefix="${DISTNAME}/" --output="$GIT_ARCHIVE" HEAD
|
|
fi
|
|
|
|
mkdir -p "$OUTDIR"
|
|
|
|
###########################
|
|
# Binary Tarball Building #
|
|
###########################
|
|
|
|
# CONFIGFLAGS
|
|
CONFIGFLAGS="-DREDUCE_EXPORTS=ON -DBUILD_BENCH=OFF -DBUILD_GUI_TESTS=OFF -DBUILD_FUZZ_BINARY=OFF"
|
|
|
|
# CFLAGS
|
|
HOST_CFLAGS="-O2 -g"
|
|
HOST_CFLAGS+=$(find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;)
|
|
case "$HOST" in
|
|
*mingw*) HOST_CFLAGS+=" -fno-ident" ;;
|
|
*darwin*) unset HOST_CFLAGS ;;
|
|
esac
|
|
|
|
# CXXFLAGS
|
|
HOST_CXXFLAGS="$HOST_CFLAGS"
|
|
|
|
case "$HOST" in
|
|
arm-linux-gnueabihf) HOST_CXXFLAGS="${HOST_CXXFLAGS} -Wno-psabi" ;;
|
|
esac
|
|
|
|
# LDFLAGS
|
|
case "$HOST" in
|
|
*linux*) HOST_LDFLAGS="-Wl,--as-needed -Wl,--dynamic-linker=$glibc_dynamic_linker -static-libstdc++ -Wl,-O2" ;;
|
|
*mingw*) HOST_LDFLAGS="-Wl,--no-insert-timestamp" ;;
|
|
esac
|
|
|
|
mkdir -p "$DISTSRC"
|
|
(
|
|
cd "$DISTSRC"
|
|
|
|
# Extract the source tarball
|
|
tar --strip-components=1 -xf "${GIT_ARCHIVE}"
|
|
|
|
# Configure this DISTSRC for $HOST
|
|
# shellcheck disable=SC2086
|
|
env CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" LDFLAGS="${HOST_LDFLAGS}" \
|
|
cmake -S . -B build \
|
|
--toolchain "${BASEPREFIX}/${HOST}/toolchain.cmake" \
|
|
-DWITH_CCACHE=OFF \
|
|
${CONFIGFLAGS}
|
|
|
|
# Build Bitcoin Core
|
|
cmake --build build -j "$JOBS" ${V:+--verbose}
|
|
|
|
# Check that symbol/security checks tools are sane.
|
|
cmake --build build --target test-security-check ${V:+--verbose}
|
|
# Perform basic security checks on a series of executables.
|
|
cmake --build build -j 1 --target check-security ${V:+--verbose}
|
|
# Check that executables only contain allowed version symbols.
|
|
cmake --build build -j 1 --target check-symbols ${V:+--verbose}
|
|
|
|
mkdir -p "$OUTDIR"
|
|
|
|
# Make the os-specific installers
|
|
case "$HOST" in
|
|
*mingw*)
|
|
cmake --build build -j "$JOBS" -t deploy ${V:+--verbose}
|
|
mv build/bitcoin-win64-setup.exe "${OUTDIR}/${DISTNAME}-win64-setup-unsigned.exe"
|
|
;;
|
|
esac
|
|
|
|
# Setup the directory where our Bitcoin Core build for HOST will be
|
|
# installed. This directory will also later serve as the input for our
|
|
# binary tarballs.
|
|
INSTALLPATH="${PWD}/installed/${DISTNAME}"
|
|
mkdir -p "${INSTALLPATH}"
|
|
# Install built Bitcoin Core to $INSTALLPATH
|
|
case "$HOST" in
|
|
*darwin*)
|
|
# This workaround can be dropped for CMake >= 3.27.
|
|
# See the upstream commit 689616785f76acd844fd448c51c5b2a0711aafa2.
|
|
find build -name 'cmake_install.cmake' -exec sed -i 's| -u -r | |g' {} +
|
|
|
|
cmake --install build --strip --prefix "${INSTALLPATH}" ${V:+--verbose}
|
|
;;
|
|
*)
|
|
cmake --install build --prefix "${INSTALLPATH}" ${V:+--verbose}
|
|
;;
|
|
esac
|
|
|
|
case "$HOST" in
|
|
*darwin*)
|
|
cmake --build build --target deploy ${V:+--verbose}
|
|
mv build/dist/Bitcoin-Core.zip "${OUTDIR}/${DISTNAME}-${HOST}-unsigned.zip"
|
|
mkdir -p "unsigned-app-${HOST}"
|
|
cp --target-directory="unsigned-app-${HOST}" \
|
|
contrib/macdeploy/detached-sig-create.sh
|
|
mv --target-directory="unsigned-app-${HOST}" build/dist
|
|
(
|
|
cd "unsigned-app-${HOST}"
|
|
find . -print0 \
|
|
| sort --zero-terminated \
|
|
| tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
|
|
| gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}-codesigning.tar.gz" \
|
|
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}-codesigning.tar.gz" && exit 1 )
|
|
)
|
|
;;
|
|
esac
|
|
(
|
|
cd installed
|
|
|
|
case "$HOST" in
|
|
*darwin*) ;;
|
|
*)
|
|
# Split binaries from their debug symbols
|
|
{
|
|
find "${DISTNAME}/bin" -type f -executable -print0
|
|
} | xargs -0 -P"$JOBS" -I{} "${DISTSRC}/build/split-debug.sh" {} {} {}.dbg
|
|
;;
|
|
esac
|
|
|
|
case "$HOST" in
|
|
*mingw*)
|
|
cp "${DISTSRC}/doc/README_windows.txt" "${DISTNAME}/readme.txt"
|
|
;;
|
|
*linux*)
|
|
cp "${DISTSRC}/README.md" "${DISTNAME}/"
|
|
;;
|
|
esac
|
|
|
|
# copy over the example bitcoin.conf file. if contrib/devtools/gen-bitcoin-conf.sh
|
|
# has not been run before buildling, this file will be a stub
|
|
cp "${DISTSRC}/share/examples/bitcoin.conf" "${DISTNAME}/"
|
|
|
|
cp -r "${DISTSRC}/share/rpcauth" "${DISTNAME}/share/"
|
|
|
|
# Finally, deterministically produce {non-,}debug binary tarballs ready
|
|
# for release
|
|
case "$HOST" in
|
|
*mingw*)
|
|
find "${DISTNAME}" -not -name "*.dbg" -print0 \
|
|
| xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}"
|
|
find "${DISTNAME}" -not -name "*.dbg" \
|
|
| sort \
|
|
| zip -X@ "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}.zip" \
|
|
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}.zip" && exit 1 )
|
|
find "${DISTNAME}" -name "*.dbg" -print0 \
|
|
| xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}"
|
|
find "${DISTNAME}" -name "*.dbg" \
|
|
| sort \
|
|
| zip -X@ "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}-debug.zip" \
|
|
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST//x86_64-w64-mingw32/win64}-debug.zip" && exit 1 )
|
|
;;
|
|
*linux*)
|
|
find "${DISTNAME}" -not -name "*.dbg" -print0 \
|
|
| sort --zero-terminated \
|
|
| tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
|
|
| gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" \
|
|
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}.tar.gz" && exit 1 )
|
|
find "${DISTNAME}" -name "*.dbg" -print0 \
|
|
| sort --zero-terminated \
|
|
| tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
|
|
| gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}-debug.tar.gz" \
|
|
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}-debug.tar.gz" && exit 1 )
|
|
;;
|
|
*darwin*)
|
|
find "${DISTNAME}" -print0 \
|
|
| sort --zero-terminated \
|
|
| tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
|
|
| gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}-unsigned.tar.gz" \
|
|
|| ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}-unsigned.tar.gz" && exit 1 )
|
|
;;
|
|
esac
|
|
) # $DISTSRC/installed
|
|
|
|
case "$HOST" in
|
|
*mingw*)
|
|
cp -rf --target-directory=. contrib/windeploy
|
|
(
|
|
cd ./windeploy
|
|
mkdir -p unsigned
|
|
cp --target-directory=unsigned/ "${OUTDIR}/${DISTNAME}-win64-setup-unsigned.exe"
|
|
find . -print0 \
|
|
| sort --zero-terminated \
|
|
| tar --create --no-recursion --mode='u+rw,go+r-w,a+X' --null --files-from=- \
|
|
| gzip -9n > "${OUTDIR}/${DISTNAME}-win64-codesigning.tar.gz" \
|
|
|| ( rm -f "${OUTDIR}/${DISTNAME}-win64-codesigning.tar.gz" && exit 1 )
|
|
)
|
|
;;
|
|
esac
|
|
) # $DISTSRC
|
|
|
|
rm -rf "$ACTUAL_OUTDIR"
|
|
mv --no-target-directory "$OUTDIR" "$ACTUAL_OUTDIR" \
|
|
|| ( rm -rf "$ACTUAL_OUTDIR" && exit 1 )
|
|
|
|
(
|
|
cd /outdir-base
|
|
{
|
|
echo "$GIT_ARCHIVE"
|
|
find "$ACTUAL_OUTDIR" -type f
|
|
} | xargs realpath --relative-base="$PWD" \
|
|
| xargs sha256sum \
|
|
| sort -k2 \
|
|
| sponge "$ACTUAL_OUTDIR"/SHA256SUMS.part
|
|
)
|