Skip to content

[Full Build - Linux (Ubuntu 20,22,24), Windows32, Windows64, MacOS] #143

[Full Build - Linux (Ubuntu 20,22,24), Windows32, Windows64, MacOS]

[Full Build - Linux (Ubuntu 20,22,24), Windows32, Windows64, MacOS] #143

name: '[Full Build - Linux (Ubuntu 20,22,24), Windows32, Windows64, MacOS]'
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
release:
types: [published]
jobs:
macos-15:
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- name: Cache Homebrew downloads
id: cache-brew-15
uses: actions/cache@v4
with:
path: |
~/Library/Caches/Homebrew
/Users/runner/Library/Caches/Homebrew
key: brew-cache-${{ runner.os }}-mac15-v1
restore-keys: |
brew-cache-${{ runner.os }}-mac15-
- name: Cache ccache
id: cache-ccache-15
uses: actions/cache@v4
with:
path: ~/.ccache
key: "ccache-${{ runner.os }}-mac15-v1-${{ hashFiles('configure.ac', 'Makefile.am', 'src/**', 'build-aux/**') }}"
restore-keys: |
ccache-${{ runner.os }}-mac15-v1-
- name: Cache Protobuf tap build (macOS 15)
id: cache-protobuf15
uses: actions/cache@v4
with:
path: /opt/homebrew/Cellar/protobuf261
key: protobuf261-${{ runner.os }}-mac15-v1-${{ hashFiles('depends/homebrew-formulas/protobuf261.rb') }}
restore-keys: |
protobuf261-${{ runner.os }}-mac15-
- name: git config credential.helper
run: git config credential.helper
- name: get previous xcode and switch to it
run: ls -la /Applications/Xcode* && sudo xcode-select -switch /Applications/Xcode_16.4.app
- name: Brew install base dependencies
run: |
brew install --quiet python@3 || brew link --overwrite python@3
brew install --quiet automake autoconf berkeley-db@4 pkg-config miniupnpc zeromq libtool qt@5 gperf qrencode librsvg ccache
- name: Brew link dependencies
run: brew link qt@5 berkeley-db@4
- name: check cellar for openssl
run: cd /opt/homebrew/Cellar/openssl@3/ && ls
- name: Configure ccache
env:
CCACHE_DIR: ~/.ccache
run: |
mkdir -p ~/.ccache
echo 'max_size = 2G' > ~/.ccache/ccache.conf
echo 'compression = true' >> ~/.ccache/ccache.conf
ccache -z || true
echo "CC=ccache clang" >> "$GITHUB_ENV"
echo "CXX=ccache clang++" >> "$GITHUB_ENV"
- name: Show current directory
run: |
pwd
git rev-parse --short HEAD
ls -lah
ls -lah depends || true
ls -lah depends/homebrew-formulas || true
- name: Create local tap & stage protobuf261.rb
run: |
set -euo pipefail
brew tap-new vergecurrency/local
TAP_DIR="$(brew --repo vergecurrency/local)"
echo "Tap dir: $TAP_DIR"
mkdir -p "$TAP_DIR/Formula"
FORMULA_LOCAL="depends/homebrew-formulas/protobuf261.rb"
if [ -f "$FORMULA_LOCAL" ]; then
echo "Using local $FORMULA_LOCAL"
cp "$FORMULA_LOCAL" "$TAP_DIR/Formula/"
else
echo "Local formula not found; fetching from repo"
REF="${GITHUB_REF_NAME:-master}"
URL="https://raw.githubusercontent.com/vergecurrency/verge/${REF}/depends/homebrew-formulas/protobuf261.rb"
echo "Fetching: $URL"
curl -fL "$URL" -o "$TAP_DIR/Formula/protobuf261.rb"
fi
echo "Current taps:"
brew tap
- name: Install protobuf261 via tap
run: brew install vergecurrency/local/protobuf261
- name: Stage boost176.rb into existing tap
run: |
set -euo pipefail
if ! brew tap | grep -q '^vergecurrency/local$'; then
brew tap-new vergecurrency/local
fi
TAP_DIR="$(brew --repo vergecurrency/local)"
echo "Tap dir: $TAP_DIR"
mkdir -p "$TAP_DIR/Formula"
FORMULA_LOCAL="depends/homebrew-formulas/boost176.rb"
if [ -f "$FORMULA_LOCAL" ]; then
echo "Using local $FORMULA_LOCAL"
cp "$FORMULA_LOCAL" "$TAP_DIR/Formula/"
else
echo "Local formula not found; fetching from repo"
REF="${GITHUB_REF_NAME:-master}"
URL="https://raw.githubusercontent.com/vergecurrency/verge/${REF}/depends/homebrew-formulas/boost176.rb"
echo "Fetching: $URL"
curl -fL "$URL" -o "$TAP_DIR/Formula/boost176.rb"
fi
echo "Current taps:"
brew tap
- name: Install boost176 via tap
run: brew install vergecurrency/local/boost176
- name: Resolve Boost 1.76 env (robust)
run: |
set -euo pipefail
BREW_PREFIX="$(brew --prefix)"
BREW_CELLAR="$(brew --cellar)"
if [ -d "$BREW_PREFIX/opt/boost176/lib" ]; then
BOOST_DIR="$BREW_PREFIX/opt/boost176"
else
CELLAR_DIR="$BREW_CELLAR/boost176"
if [ -d "$CELLAR_DIR" ]; then
BOOST_VER="$(ls -1 "$CELLAR_DIR" | sort -V | tail -n1 || true)"
if [ -n "${BOOST_VER:-}" ] && [ -d "$CELLAR_DIR/$BOOST_VER/lib" ]; then
BOOST_DIR="$CELLAR_DIR/$BOOST_VER"
fi
fi
fi
echo "Resolved BOOST_DIR=${BOOST_DIR:-<empty>}"
if [ -z "${BOOST_DIR:-}" ] || [ ! -d "$BOOST_DIR/lib" ]; then
echo "::error::Boost libdir not found."
exit 1
fi
echo "BOOST_ROOT=$BOOST_DIR" >> "$GITHUB_ENV"
echo "BOOST_INCLUDEDIR=$BOOST_DIR/include" >> "$GITHUB_ENV"
echo "BOOST_LIBRARYDIR=$BOOST_DIR/lib" >> "$GITHUB_ENV"
echo "CPPFLAGS=-I$BOOST_DIR/include" >> "$GITHUB_ENV"
echo "LDFLAGS=-L$BOOST_DIR/lib" >> "$GITHUB_ENV"
- name: Resolve Protobuf 2.6.1 env (robust)
run: |
set -euo pipefail
BREW_PREFIX="$(brew --prefix)"
BREW_CELLAR="$(brew --cellar)"
if [ -d "$BREW_PREFIX/opt/protobuf261/lib" ]; then
PROTO_DIR="$BREW_PREFIX/opt/protobuf261"
else
CELLAR_DIR="$BREW_CELLAR/protobuf261"
if [ -d "$CELLAR_DIR" ]; then
PROTO_VER="$(ls -1 "$CELLAR_DIR" | sort -V | tail -n1 || true)"
if [ -n "${PROTO_VER:-}" ] && [ -d "$CELLAR_DIR/$PROTO_VER/lib" ]; then
PROTO_DIR="$CELLAR_DIR/$PROTO_VER"
fi
fi
fi
echo "Resolved PROTO_DIR=${PROTO_DIR:-<empty>}"
if [ -z "${PROTO_DIR:-}" ] || [ ! -d "$PROTO_DIR/lib" ]; then
echo "::error::Protobuf libdir not found."
exit 1
fi
echo "PROTOBUF_ROOT=$PROTO_DIR" >> "$GITHUB_ENV"
echo "PROTOBUF_INCLUDEDIR=$PROTO_DIR/include" >> "$GITHUB_ENV"
echo "PROTOBUF_LIBRARYDIR=$PROTO_DIR/lib" >> "$GITHUB_ENV"
echo "PKG_CONFIG_PATH=$PROTO_DIR/lib/pkgconfig:${PKG_CONFIG_PATH:-}" >> "$GITHUB_ENV"
echo "PATH=$PROTO_DIR/bin:$(brew --prefix)/bin:$(brew --prefix)/sbin:${PATH:-/usr/bin:/bin}" >> "$GITHUB_ENV"
BOOST_INC="${BOOST_INCLUDEDIR:-}"
BOOST_LIB="${BOOST_LIBRARYDIR:-}"
echo "CPPFLAGS=${BOOST_INC:+-I$BOOST_INC }-I$PROTO_DIR/include" >> "$GITHUB_ENV"
echo "LDFLAGS=${BOOST_LIB:+-L$BOOST_LIB }-L$PROTO_DIR/lib" >> "$GITHUB_ENV"
[ -z "${BOOST_INC}" ] || test -f "$BOOST_INC/boost/filesystem.hpp" || { echo "::warning::boost/filesystem.hpp not found under $BOOST_INC"; ls -R "$BOOST_INC" | head -n 50 || true; }
ls -lah "$PROTO_DIR/lib" | grep -E 'libprotobuf|protobuf' || true
- name: which clang/xcode
run: clang --version
- name: Auto generate
run: ./autogen.sh
- name: configure
run: |
./configure \
--disable-bench \
--disable-tests \
--disable-dependency-tracking \
--disable-werror \
--with-gui \
--with-boost="${BOOST_ROOT}" \
--with-boost-libdir="${BOOST_LIBRARYDIR}" \
--bindir="$(pwd)/release/bin" \
--libdir="$(pwd)/release/lib" \
--with-openssl-dir=/opt/homebrew/Cellar/openssl@3/3.6.0 \
--with-libevent-dir=/opt/homebrew/Cellar/libevent/2.1.12_1
- name: make
run: make -j4
# ---- SAFE BOOST SETUP (no /opt relink, no self-loop symlinks) ----
- name: Prepare Boost dylib names for macdeploy (safe, no opt relink)
run: |
set -euo pipefail
BREW_CELLAR="$(brew --cellar)"
# Prefer real keg path
if [ -n "${BOOST_LIBRARYDIR:-}" ] && [ -d "$BOOST_LIBRARYDIR" ]; then
BOOST_LIB_DIR="$BOOST_LIBRARYDIR"
else
KEG_DIR="$(ls -1d "$BREW_CELLAR/boost176"/* 2>/dev/null | sort -V | tail -n1 || true)"
[ -n "$KEG_DIR" ] || { echo "::error::No boost176 keg found in $BREW_CELLAR/boost176"; exit 1; }
BOOST_LIB_DIR="$KEG_DIR/lib"
fi
echo "Using BOOST_LIB_DIR=$BOOST_LIB_DIR"
fix_boost_symlink() {
local base="$1"
local plain="$BOOST_LIB_DIR/libboost_${base}.dylib"
if [ ! -e "$plain" ]; then
# choose a candidate that is NOT the plain name to avoid self-loop
CAND="$(ls -1 "$BOOST_LIB_DIR"/libboost_${base}*.dylib 2>/dev/null | \
grep -Ev '/libboost_'"$base"'\.dylib$' | sort -V | tail -n1 || true)"
if [ -n "$CAND" ]; then
[ "$(basename "$CAND")" = "libboost_${base}.dylib" ] || ln -sf "$(basename "$CAND")" "$plain"
fi
fi
( ls -l "$BOOST_LIB_DIR"/libboost_${base}*.dylib || true ) | sed -n '1,10p'
}
for L in filesystem program_options thread chrono system; do
fix_boost_symlink "$L"
done
echo "DYLD_LIBRARY_PATH=$BOOST_LIB_DIR:${DYLD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
echo "BOOST_LIBS=$BOOST_LIB_DIR" >> "$GITHUB_ENV"
- name: Prepare Protobuf dylib for macdeploy
run: |
set -euo pipefail
BREW_PREFIX="$(brew --prefix)"
BREW_CELLAR="$(brew --cellar)"
if [ -n "${PROTOBUF_LIBRARYDIR:-}" ] && [ -d "$PROTOBUF_LIBRARYDIR" ]; then
PROTO_DIR="$(dirname "$PROTOBUF_LIBRARYDIR")"
PROTO_LIB_DIR="$PROTOBUF_LIBRARYDIR"
elif [ -d "$BREW_PREFIX/opt/protobuf261/lib" ]; then
PROTO_DIR="$BREW_PREFIX/opt/protobuf261"
PROTO_LIB_DIR="$PROTO_DIR/lib"
else
CELLAR_DIR="$BREW_CELLAR/protobuf261"
PROTO_VER="$(ls -1 "$CELLAR_DIR" | sort -V | tail -n1 || true)"
PROTO_DIR="$CELLAR_DIR/$PROTO_VER"
PROTO_LIB_DIR="$PROTO_DIR/lib"
fi
echo "Using PROTO_DIR=$PROTO_DIR"
echo "Using PROTO_LIB_DIR=$PROTO_LIB_DIR"
[ -f "$PROTO_LIB_DIR/libprotobuf.9.dylib" ] || {
[ -f "$PROTO_LIB_DIR/libprotobuf.dylib" ] && ln -sf "libprotobuf.dylib" "$PROTO_LIB_DIR/libprotobuf.9.dylib"
}
echo "DYLD_LIBRARY_PATH=$PROTO_LIB_DIR:${DYLD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
# ---- REPAIR /opt SYMLINKS & ASSERT DYLIBS (protobuf + boost) ----
- name: Repair /opt symlinks & assert dylibs (protobuf+boost)
run: |
set -euo pipefail
BREW_PREFIX="$(brew --prefix)"
BREW_CELLAR="$(brew --cellar)"
# --- Protobuf: ensure /opt points at the active keg and .9 shim exists ---
PROTO_DIR="${PROTOBUF_ROOT:?missing PROTOBUF_ROOT}"
# Normalize to real keg path
if [ -L "$PROTO_DIR" ]; then PROTO_DIR="$(realpath "$PROTO_DIR")"; fi
if [ ! -L "$BREW_PREFIX/opt/protobuf261" ] || [ "$(realpath "$BREW_PREFIX/opt/protobuf261" || true)" != "$PROTO_DIR" ]; then
sudo rm -rf "$BREW_PREFIX/opt/protobuf261" || true
sudo ln -s "$PROTO_DIR" "$BREW_PREFIX/opt/protobuf261"
fi
for BASE in "$PROTO_DIR/lib" "$BREW_PREFIX/opt/protobuf261/lib"; do
[ -d "$BASE" ] || continue
for LIB in protobuf protobuf-lite; do
if [ ! -f "$BASE/lib${LIB}.9.dylib" ] && [ -f "$BASE/lib${LIB}.dylib" ]; then
ln -sf "lib${LIB}.dylib" "$BASE/lib${LIB}.9.dylib"
fi
done
done
echo "Protobuf opt target -> $(readlink $BREW_PREFIX/opt/protobuf261 || true)"
ls -ld "$BREW_PREFIX/opt/protobuf261" || true
ls -l "$BREW_PREFIX/opt/protobuf261/lib" | sed -n '1,80p' || true
# --- Boost: relink /opt to the REAL keg (avoid self-loop) ---
KEG_DIR="$(ls -1d "$BREW_CELLAR/boost176"/* 2>/dev/null | sort -V | tail -n1 || true)"
[ -n "$KEG_DIR" ] || { echo "::error::No boost176 keg found"; exit 1; }
BOOST_KEG="$KEG_DIR"
if [ ! -L "$BREW_PREFIX/opt/boost176" ] || [ "$(realpath "$BREW_PREFIX/opt/boost176" || true)" != "$BOOST_KEG" ]; then
sudo rm -rf "$BREW_PREFIX/opt/boost176" || true
sudo ln -s "$BOOST_KEG" "$BREW_PREFIX/opt/boost176"
fi
BOOST_LIB_DIR="$BOOST_KEG/lib"
for L in filesystem program_options thread chrono system; do
PLAIN="$BOOST_LIB_DIR/libboost_${L}.dylib"
if [ ! -e "$PLAIN" ]; then
CAND="$(ls -1 "$BOOST_LIB_DIR"/libboost_${L}*.dylib 2>/dev/null | grep -v '/libboost_'"$L"'\.dylib$' | sort -V | tail -n1 || true)"
[ -n "$CAND" ] && [ "$(basename "$CAND")" = "libboost_${L}.dylib" ] || { [ -n "$CAND" ] && ln -sf "$(basename "$CAND")" "$PLAIN"; }
fi
done
echo "Boost opt target -> $(readlink $BREW_PREFIX/opt/boost176 || true)"
ls -ld "$BREW_PREFIX/opt/boost176" || true
ls -l "$BOOST_LIB_DIR" | grep -E 'boost_(filesystem|program_options|thread|chrono|system).*dylib' || true
# Export final DYLD path from real kegs
echo "DYLD_LIBRARY_PATH=$PROTO_DIR/lib:$BOOST_LIB_DIR:${DYLD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
- name: make .dmg
run: |
set -euo pipefail
# Guard: verify plain-name Boost dylibs from the REAL keg (not /opt, to avoid loops)
BREW_CELLAR="$(brew --cellar)"
KEG_DIR="$(ls -1d "$BREW_CELLAR/boost176"/* 2>/dev/null | sort -V | tail -n1 || true)"
BOOST_LIB_DIR="${BOOST_LIBS:-${BOOST_LIBRARYDIR:-${KEG_DIR}/lib}}"
for L in filesystem program_options thread chrono system; do
test -f "$BOOST_LIB_DIR/libboost_${L}.dylib" || {
echo "::error::Missing $BOOST_LIB_DIR/libboost_${L}.dylib"
ls -lah "$BOOST_LIB_DIR" | sed -n '1,200p' || true
exit 1
}
done
# Final guard for the exact path macdeployqtplus wants:
test -f /opt/homebrew/opt/protobuf261/lib/libprotobuf.9.dylib
echo "Boost dylibs OK in $BOOST_LIB_DIR"
echo "DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH"
make deploy
- name: Ad-hoc sign Verge binaries (macOS 15)
run: |
set -euo pipefail
echo "Searching for Verge binaries to sign…"
find . -type f \( \
-name "verge-qt" -o \
-name "verged" -o \
-name "verge-cli" -o \
-name "verge-tx" \
\) -print -exec codesign --force --sign - {} \;
# If Qt app exists, sign the whole bundle (important)
if ls *.app >/dev/null 2>&1; then
for APP in *.app; do
echo "Ad-hoc signing app bundle: $APP"
codesign --force --deep --sign - "$APP"
done
fi
echo "Verifying signatures:"
find . -type f \( \
-name "verge-qt" -o \
-name "verged" -o \
-name "verge-cli" -o \
-name "verge-tx" \
\) -exec codesign -vv {} \; || true
- uses: actions/upload-artifact@v4
with:
name: verge-macos15
path: |
*.dmg
macos-14:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Cache Homebrew downloads
id: cache-brew-14
uses: actions/cache@v4
with:
path: |
~/Library/Caches/Homebrew
/Users/runner/Library/Caches/Homebrew
key: brew-cache-${{ runner.os }}-mac14-v1
restore-keys: |
brew-cache-${{ runner.os }}-mac14-
- name: Cache ccache
id: cache-ccache-14
uses: actions/cache@v4
with:
path: ~/.ccache
key: ccache-${{ runner.os }}-mac14-v1-${{ hashFiles('configure.ac', 'Makefile.am', 'src/**', 'build-aux/**') }}
restore-keys: |
ccache-${{ runner.os }}-mac14-v1-
- name: Cache Protobuf tap build (macOS 14)
id: cache-protobuf14
uses: actions/cache@v4
with:
path: /opt/homebrew/Cellar/protobuf261
key: protobuf261-${{ runner.os }}-mac14-v1-${{ hashFiles('depends/homebrew-formulas/protobuf261.rb') }}
restore-keys: |
protobuf261-${{ runner.os }}-mac14-
- name: git config credential.helper
run: git config credential.helper
- name: get previous xcode and switch to it
run: ls -la /Applications/Xcode* && sudo xcode-select -switch /Applications/Xcode_15.2.app
- name: Brew install base dependencies
run: |
brew install --quiet python@3 || brew link --overwrite python@3
brew install --quiet automake autoconf berkeley-db@4 pkg-config miniupnpc zeromq libtool qt@5 gperf qrencode librsvg ccache
- name: Brew link dependencies
run: brew link qt@5 berkeley-db@4
- name: check cellar for openssl
run: cd /opt/homebrew/Cellar/openssl@3/ && ls
- name: Configure ccache
env:
CCACHE_DIR: ~/.ccache
run: |
mkdir -p ~/.ccache
echo 'max_size = 2G' > ~/.ccache/ccache.conf
echo 'compression = true' >> ~/.ccache/ccache.conf
ccache -z || true
echo "CC=ccache clang" >> "$GITHUB_ENV"
echo "CXX=ccache clang++" >> "$GITHUB_ENV"
- name: Show current directory
run: |
pwd
git rev-parse --short HEAD
ls -lah
ls -lah depends || true
ls -lah depends/homebrew-formulas || true
- name: Create local tap & stage protobuf261.rb
run: |
set -euo pipefail
brew tap-new vergecurrency/local
TAP_DIR="$(brew --repo vergecurrency/local)"
echo "Tap dir: $TAP_DIR"
mkdir -p "$TAP_DIR/Formula"
FORMULA_LOCAL="depends/homebrew-formulas/protobuf261.rb"
if [ -f "$FORMULA_LOCAL" ]; then
echo "Using local $FORMULA_LOCAL"
cp "$FORMULA_LOCAL" "$TAP_DIR/Formula/"
else
echo "Local formula not found; fetching from repo"
REF="${GITHUB_REF_NAME:-master}"
URL="https://raw.githubusercontent.com/vergecurrency/verge/${REF}/depends/homebrew-formulas/protobuf261.rb"
echo "Fetching: $URL"
curl -fL "$URL" -o "$TAP_DIR/Formula/protobuf261.rb"
fi
echo "Current taps:"
brew tap
- name: Install protobuf261 via tap
run: brew install vergecurrency/local/protobuf261
- name: Stage boost176.rb into existing tap
run: |
set -euo pipefail
if ! brew tap | grep -q '^vergecurrency/local$'; then
brew tap-new vergecurrency/local
fi
TAP_DIR="$(brew --repo vergecurrency/local)"
echo "Tap dir: $TAP_DIR"
mkdir -p "$TAP_DIR/Formula"
FORMULA_LOCAL="depends/homebrew-formulas/boost176.rb"
if [ -f "$FORMULA_LOCAL" ]; then
echo "Using local $FORMULA_LOCAL"
cp "$FORMULA_LOCAL" "$TAP_DIR/Formula/"
else
echo "Local formula not found; fetching from repo"
REF="${GITHUB_REF_NAME:-master}"
URL="https://raw.githubusercontent.com/vergecurrency/verge/${REF}/depends/homebrew-formulas/boost176.rb"
echo "Fetching: $URL"
curl -fL "$URL" -o "$TAP_DIR/Formula/boost176.rb"
fi
echo "Current taps:"
brew tap
- name: Install boost176 via tap
run: brew install vergecurrency/local/boost176
- name: Resolve Boost 1.76 env (robust)
run: |
set -euo pipefail
BREW_PREFIX="$(brew --prefix)"
BREW_CELLAR="$(brew --cellar)"
if [ -d "$BREW_PREFIX/opt/boost176/lib" ]; then
BOOST_DIR="$BREW_PREFIX/opt/boost176"
else
CELLAR_DIR="$BREW_CELLAR/boost176"
if [ -d "$CELLAR_DIR" ]; then
BOOST_VER="$(ls -1 "$CELLAR_DIR" | sort -V | tail -n1 || true)"
if [ -n "${BOOST_VER:-}" ] && [ -d "$CELLAR_DIR/$BOOST_VER/lib" ]; then
BOOST_DIR="$CELLAR_DIR/$BOOST_VER"
fi
fi
fi
echo "Resolved BOOST_DIR=${BOOST_DIR:-<empty>}"
if [ -z "${BOOST_DIR:-}" ] || [ ! -d "$BOOST_DIR/lib" ]; then
echo "::error::Boost libdir not found."
exit 1
fi
echo "BOOST_ROOT=$BOOST_DIR" >> "$GITHUB_ENV"
echo "BOOST_INCLUDEDIR=$BOOST_DIR/include" >> "$GITHUB_ENV"
echo "BOOST_LIBRARYDIR=$BOOST_DIR/lib" >> "$GITHUB_ENV"
echo "CPPFLAGS=-I$BOOST_DIR/include" >> "$GITHUB_ENV"
echo "LDFLAGS=-L$BOOST_DIR/lib" >> "$GITHUB_ENV"
- name: Resolve Protobuf 2.6.1 env (robust)
run: |
set -euo pipefail
BREW_PREFIX="$(brew --prefix)"
BREW_CELLAR="$(brew --cellar)"
if [ -d "$BREW_PREFIX/opt/protobuf261/lib" ]; then
PROTO_DIR="$BREW_PREFIX/opt/protobuf261"
else
CELLAR_DIR="$BREW_CELLAR/protobuf261"
if [ -d "$CELLAR_DIR" ]; then
PROTO_VER="$(ls -1 "$CELLAR_DIR" | sort -V | tail -n1 || true)"
if [ -n "${PROTO_VER:-}" ] && [ -d "$CELLAR_DIR/$PROTO_VER/lib" ]; then
PROTO_DIR="$CELLAR_DIR/$PROTO_VER"
fi
fi
fi
echo "Resolved PROTO_DIR=${PROTO_DIR:-<empty>}"
if [ -z "${PROTO_DIR:-}" ] || [ ! -d "$PROTO_DIR/lib" ]; then
echo "::error::Protobuf libdir not found."
exit 1
fi
echo "PROTOBUF_ROOT=$PROTO_DIR" >> "$GITHUB_ENV"
echo "PROTOBUF_INCLUDEDIR=$PROTO_DIR/include" >> "$GITHUB_ENV"
echo "PROTOBUF_LIBRARYDIR=$PROTO_DIR/lib" >> "$GITHUB_ENV"
echo "PKG_CONFIG_PATH=$PROTO_DIR/lib/pkgconfig:${PKG_CONFIG_PATH:-}" >> "$GITHUB_ENV"
echo "PATH=$PROTO_DIR/bin:$(brew --prefix)/bin:$(brew --prefix)/sbin:${PATH:-/usr/bin:/bin}" >> "$GITHUB_ENV"
BOOST_INC="${BOOST_INCLUDEDIR:-}"
BOOST_LIB="${BOOST_LIBRARYDIR:-}"
echo "CPPFLAGS=${BOOST_INC:+-I$BOOST_INC }-I$PROTO_DIR/include" >> "$GITHUB_ENV"
echo "LDFLAGS=${BOOST_LIB:+-L$BOOST_LIB }-L$PROTO_DIR/lib" >> "$GITHUB_ENV"
[ -z "${BOOST_INC}" ] || test -f "$BOOST_INC/boost/filesystem.hpp" || { echo "::warning::boost/filesystem.hpp not found under $BOOST_INC"; ls -R "$BOOST_INC" | head -n 50 || true; }
ls -lah "$PROTO_DIR/lib" | grep -E 'libprotobuf|protobuf' || true
- name: which clang/xcode
run: clang --version
- name: Auto generate
run: ./autogen.sh
- name: configure
run: |
./configure \
--disable-bench \
--disable-tests \
--disable-dependency-tracking \
--disable-werror \
--with-gui \
--with-boost="${BOOST_ROOT}" \
--with-boost-libdir="${BOOST_LIBRARYDIR}" \
--bindir="$(pwd)/release/bin" \
--libdir="$(pwd)/release/lib" \
--with-openssl-dir=/opt/homebrew/Cellar/openssl@3/3.6.0 \
--with-libevent-dir=/opt/homebrew/Cellar/libevent/2.1.12_1
- name: make
run: make -j4
# ---- SAFE BOOST SETUP (no /opt relink, no self-loop symlinks) ----
- name: Prepare Boost dylib names for macdeploy (safe, no opt relink)
run: |
set -euo pipefail
BREW_CELLAR="$(brew --cellar)"
# Prefer real keg path
if [ -n "${BOOST_LIBRARYDIR:-}" ] && [ -d "$BOOST_LIBRARYDIR" ]; then
BOOST_LIB_DIR="$BOOST_LIBRARYDIR"
else
KEG_DIR="$(ls -1d "$BREW_CELLAR/boost176"/* 2>/dev/null | sort -V | tail -n1 || true)"
[ -n "$KEG_DIR" ] || { echo "::error::No boost176 keg found in $BREW_CELLAR/boost176"; exit 1; }
BOOST_LIB_DIR="$KEG_DIR/lib"
fi
echo "Using BOOST_LIB_DIR=$BOOST_LIB_DIR"
fix_boost_symlink() {
local base="$1"
local plain="$BOOST_LIB_DIR/libboost_${base}.dylib"
if [ ! -e "$plain" ]; then
# choose a candidate that is NOT the plain name to avoid self-loop
CAND="$(ls -1 "$BOOST_LIB_DIR"/libboost_${base}*.dylib 2>/dev/null | \
grep -Ev '/libboost_'"$base"'\.dylib$' | sort -V | tail -n1 || true)"
if [ -n "$CAND" ]; then
[ "$(basename "$CAND")" = "libboost_${base}.dylib" ] || ln -sf "$(basename "$CAND")" "$plain"
fi
fi
( ls -l "$BOOST_LIB_DIR"/libboost_${base}*.dylib || true ) | sed -n '1,10p'
}
for L in filesystem program_options thread chrono system; do
fix_boost_symlink "$L"
done
echo "DYLD_LIBRARY_PATH=$BOOST_LIB_DIR:${DYLD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
echo "BOOST_LIBS=$BOOST_LIB_DIR" >> "$GITHUB_ENV"
- name: Prepare Protobuf dylib for macdeploy
run: |
set -euo pipefail
BREW_PREFIX="$(brew --prefix)"
BREW_CELLAR="$(brew --cellar)"
if [ -n "${PROTOBUF_LIBRARYDIR:-}" ] && [ -d "$PROTOBUF_LIBRARYDIR" ]; then
PROTO_DIR="$(dirname "$PROTOBUF_LIBRARYDIR")"
PROTO_LIB_DIR="$PROTOBUF_LIBRARYDIR"
elif [ -d "$BREW_PREFIX/opt/protobuf261/lib" ]; then
PROTO_DIR="$BREW_PREFIX/opt/protobuf261"
PROTO_LIB_DIR="$PROTO_DIR/lib"
else
CELLAR_DIR="$BREW_CELLAR/protobuf261"
PROTO_VER="$(ls -1 "$CELLAR_DIR" | sort -V | tail -n1 || true)"
PROTO_DIR="$CELLAR_DIR/$PROTO_VER"
PROTO_LIB_DIR="$PROTO_DIR/lib"
fi
echo "Using PROTO_DIR=$PROTO_DIR"
echo "Using PROTO_LIB_DIR=$PROTO_LIB_DIR"
[ -f "$PROTO_LIB_DIR/libprotobuf.9.dylib" ] || {
[ -f "$PROTO_LIB_DIR/libprotobuf.dylib" ] && ln -sf "libprotobuf.dylib" "$PROTO_LIB_DIR/libprotobuf.9.dylib"
}
echo "DYLD_LIBRARY_PATH=$PROTO_LIB_DIR:${DYLD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
# ---- REPAIR /opt SYMLINKS & ASSERT DYLIBS (protobuf + boost) ----
- name: Repair /opt symlinks & assert dylibs (protobuf+boost)
run: |
set -euo pipefail
BREW_PREFIX="$(brew --prefix)"
BREW_CELLAR="$(brew --cellar)"
# --- Protobuf: ensure /opt points at the active keg and .9 shim exists ---
PROTO_DIR="${PROTOBUF_ROOT:?missing PROTOBUF_ROOT}"
# Normalize to real keg path
if [ -L "$PROTO_DIR" ]; then PROTO_DIR="$(realpath "$PROTO_DIR")"; fi
if [ ! -L "$BREW_PREFIX/opt/protobuf261" ] || [ "$(realpath "$BREW_PREFIX/opt/protobuf261" || true)" != "$PROTO_DIR" ]; then
sudo rm -rf "$BREW_PREFIX/opt/protobuf261" || true
sudo ln -s "$PROTO_DIR" "$BREW_PREFIX/opt/protobuf261"
fi
for BASE in "$PROTO_DIR/lib" "$BREW_PREFIX/opt/protobuf261/lib"; do
[ -d "$BASE" ] || continue
for LIB in protobuf protobuf-lite; do
if [ ! -f "$BASE/lib${LIB}.9.dylib" ] && [ -f "$BASE/lib${LIB}.dylib" ]; then
ln -sf "lib${LIB}.dylib" "$BASE/lib${LIB}.9.dylib"
fi
done
done
echo "Protobuf opt target -> $(readlink $BREW_PREFIX/opt/protobuf261 || true)"
ls -ld "$BREW_PREFIX/opt/protobuf261" || true
ls -l "$BREW_PREFIX/opt/protobuf261/lib" | sed -n '1,80p' || true
# --- Boost: relink /opt to the REAL keg (avoid self-loop) ---
KEG_DIR="$(ls -1d "$BREW_CELLAR/boost176"/* 2>/dev/null | sort -V | tail -n1 || true)"
[ -n "$KEG_DIR" ] || { echo "::error::No boost176 keg found"; exit 1; }
BOOST_KEG="$KEG_DIR"
if [ ! -L "$BREW_PREFIX/opt/boost176" ] || [ "$(realpath "$BREW_PREFIX/opt/boost176" || true)" != "$BOOST_KEG" ]; then
sudo rm -rf "$BREW_PREFIX/opt/boost176" || true
sudo ln -s "$BOOST_KEG" "$BREW_PREFIX/opt/boost176"
fi
BOOST_LIB_DIR="$BOOST_KEG/lib"
for L in filesystem program_options thread chrono system; do
PLAIN="$BOOST_LIB_DIR/libboost_${L}.dylib"
if [ ! -e "$PLAIN" ]; then
CAND="$(ls -1 "$BOOST_LIB_DIR"/libboost_${L}*.dylib 2>/dev/null | grep -v '/libboost_'"$L"'\.dylib$' | sort -V | tail -n1 || true)"
[ -n "$CAND" ] && [ "$(basename "$CAND")" = "libboost_${L}.dylib" ] || { [ -n "$CAND" ] && ln -sf "$(basename "$CAND")" "$PLAIN"; }
fi
done
echo "Boost opt target -> $(readlink $BREW_PREFIX/opt/boost176 || true)"
ls -ld "$BREW_PREFIX/opt/boost176" || true
ls -l "$BOOST_LIB_DIR" | grep -E 'boost_(filesystem|program_options|thread|chrono|system).*dylib' || true
# Export final DYLD path from real kegs
echo "DYLD_LIBRARY_PATH=$PROTO_DIR/lib:$BOOST_LIB_DIR:${DYLD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
- name: make .dmg
run: |
set -euo pipefail
# Guard: verify plain-name Boost dylibs from the REAL keg (not /opt, to avoid loops)
BREW_CELLAR="$(brew --cellar)"
KEG_DIR="$(ls -1d "$BREW_CELLAR/boost176"/* 2>/dev/null | sort -V | tail -n1 || true)"
BOOST_LIB_DIR="${BOOST_LIBS:-${BOOST_LIBRARYDIR:-${KEG_DIR}/lib}}"
for L in filesystem program_options thread chrono system; do
test -f "$BOOST_LIB_DIR/libboost_${L}.dylib" || {
echo "::error::Missing $BOOST_LIB_DIR/libboost_${L}.dylib"
ls -lah "$BOOST_LIB_DIR" | sed -n '1,200p' || true
exit 1
}
done
# Final guard for the exact path macdeployqtplus wants:
test -f /opt/homebrew/opt/protobuf261/lib/libprotobuf.9.dylib
echo "Boost dylibs OK in $BOOST_LIB_DIR"
echo "DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH"
make deploy
- name: Ad-hoc sign Verge binaries (macOS 14)
run: |
set -euo pipefail
echo "Searching for Verge binaries to sign…"
find . -type f \( \
-name "verge-qt" -o \
-name "verged" -o \
-name "verge-cli" -o \
-name "verge-tx" \
\) -print -exec codesign --force --sign - {} \;
if ls *.app >/dev/null 2>&1; then
for APP in *.app; do
echo "Ad-hoc signing app bundle: $APP"
codesign --force --deep --sign - "$APP"
done
fi
echo "Verifying signatures:"
find . -type f \( \
-name "verge-qt" -o \
-name "verged" -o \
-name "verge-cli" -o \
-name "verge-tx" \
\) -exec codesign -vv {} \; || true
- uses: actions/upload-artifact@v4
with:
name: verge-macos14
path: |
*.dmg
ubuntu24:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Update apt repos
run: sudo apt-get update
- name: Install base dependencies
run: sudo apt-get install -y build-essential xutils-dev libtool gperf autotools-dev automake pkg-config bsdmainutils libattr1-dev make automake bison byacc cmake curl g++-multilib binutils-gold python3
- name: Build depends
run: cd depends/ && make -j4 HOST=x86_64-linux-gnu
- name: Auto generate
run: ./autogen.sh
- name: configure
run: CONFIG_SITE=$PWD/depends/x86_64-linux-gnu/share/config.site ./configure --disable-bench --disable-tests --disable-dependency-tracking --disable-werror --prefix=$(pwd)/depends/x86_64-linux-gnu --bindir=$(pwd)/release/bin --libdir=$(pwd)/release/lib
- name: make
run: make -j4
- name: strip
run: |
strip ./src/verged
strip ./src/verge-cli
strip ./src/verge-tx
strip ./src/qt/verge-qt
- uses: actions/upload-artifact@v4
with:
name: verge-ubuntu24
path: |
./src/verged
./src/verge-cli
./src/verge-tx
./src/qt/verge-qt
ubuntu22:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Update apt repos
run: sudo apt-get update
- name: Install base dependencies
run: sudo apt-get install -y build-essential xutils-dev libtool gperf autotools-dev automake pkg-config bsdmainutils libattr1-dev make automake bison byacc cmake curl g++-multilib binutils-gold python3
- name: Build depends
run: cd depends/ && make -j4 HOST=x86_64-linux-gnu
- name: Auto generate
run: ./autogen.sh
- name: configure
run: CONFIG_SITE=$PWD/depends/x86_64-linux-gnu/share/config.site ./configure --disable-bench --disable-tests --disable-dependency-tracking --disable-werror --prefix=$(pwd)/depends/x86_64-linux-gnu --bindir=$(pwd)/release/bin --libdir=$(pwd)/release/lib
- name: make
run: make -j4
- name: strip
run: |
strip ./src/verged
strip ./src/verge-cli
strip ./src/verge-tx
strip ./src/qt/verge-qt
- uses: actions/upload-artifact@v4
with:
name: verge-ubuntu22
path: |
./src/verged
./src/verge-cli
./src/verge-tx
./src/qt/verge-qt
windows32:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Update apt repos
run: sudo apt-get update
- name: Install base dependencies
run: sudo apt-get install -y build-essential libtool gperf autotools-dev automake pkg-config bsdmainutils curl git bison byacc python3 nsis
- name: Force Posix
run: |
sudo apt-get install -y g++-mingw-w64-i686 mingw-w64-i686-dev
sudo update-alternatives --set i686-w64-mingw32-g++ /usr/bin/i686-w64-mingw32-g++-posix
- name: Build depends for MingW32 Cross Compile
run: PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g') && cd depends/ && make HOST=i686-w64-mingw32 -j2
- name: Auto generate
run: ./autogen.sh
- name: configure
run: CONFIG_SITE=$PWD/depends/i686-w64-mingw32/share/config.site ./configure --prefix=/ --disable-bench --disable-tests
- name: make
run: make -j2
- name: strip
run: |
cd ./src && strip verged.exe verge-cli.exe verge-tx.exe
cd ./qt && strip verge-qt.exe
- uses: actions/upload-artifact@v4
with:
name: verge-windows32
path: |
./src/verged.exe
./src/verge-cli.exe
./src/verge-tx.exe
./src/qt/verge-qt.exe
windows64:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Update apt repos
run: sudo apt-get update
- name: Install base dependencies
run: sudo apt-get install -y build-essential libtool gperf autotools-dev automake pkg-config bsdmainutils curl git bison byacc python3 nsis
- name: Force Posix
run: |
sudo apt install -y g++-mingw-w64-x86-64
sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
- name: Build depends for MingW64 Cross Compile
run: PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g') && cd depends/ && make HOST=x86_64-w64-mingw32 -j2
- name: Auto generate
run: ./autogen.sh
- name: configure
run: CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site ./configure --prefix=/ --disable-bench --disable-tests
- name: make
run: make -j2
- name: strip
run: |
cd ./src && strip verged.exe verge-cli.exe verge-tx.exe
cd ./qt && strip verge-qt.exe
- uses: actions/upload-artifact@v4
with:
name: verge-windows64
path: |
./src/verged.exe
./src/verge-cli.exe
./src/verge-tx.exe
./src/qt/verge-qt.exe
SendReleases:
runs-on: ubuntu-latest
needs: [macos-15, macos-14, ubuntu22, ubuntu24, windows32, windows64]
env:
TAG_NAME: v8.0.3
steps:
- name: Checkout (full history for changelog/contributors)
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate empty Changelog (fallback)
run: echo "# Changelog" > ${{ github.workspace }}-CHANGELOG.txt
- uses: actions/download-artifact@v4
with:
name: verge-windows32
path: verge-windows32
- uses: actions/download-artifact@v4
with:
name: verge-windows64
path: verge-windows64
- uses: actions/download-artifact@v4
with:
name: verge-macos15
path: verge-macos15
- uses: actions/download-artifact@v4
with:
name: verge-macos14
path: verge-macos14
- uses: actions/download-artifact@v4
with:
name: verge-ubuntu22
path: verge-ubuntu22
- uses: actions/download-artifact@v4
with:
name: verge-ubuntu24
path: verge-ubuntu24
- name: Create zips
run: |
zip -r verge-windows32.zip verge-windows32/
zip -r verge-windows64.zip verge-windows64/
zip -r verge-macos15.zip verge-macos15/
zip -r verge-macos14.zip verge-macos14/
zip -r verge-ubuntu22.zip verge-ubuntu22/
zip -r verge-ubuntu24.zip verge-ubuntu24/
- name: List downloaded artifacts
run: ls -lR
- name: sha256
run: |
find . -type f -name "*.zip" | LC_ALL=C sort | xargs sha256sum -b > SHA256SUMS.txt
cat SHA256SUMS.txt
- name: Derive previous tag and metadata
id: meta
shell: bash
run: |
set -euo pipefail
TAG="${TAG_NAME}"
if git rev-parse -q --verify "refs/tags/${TAG}^{}" >/dev/null 2>&1; then
PREV_TAG="$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || true)"
RANGE_START="${PREV_TAG:-$(git rev-list --max-parents=0 HEAD)}"
RANGE_END="${TAG}"
else
PREV_TAG="$(git describe --tags --abbrev=0 2>/dev/null || true)"
RANGE_START="${PREV_TAG:-$(git rev-list --max-parents=0 HEAD)}"
RANGE_END="HEAD"
fi
COMMIT_SHA="$(git rev-parse --short HEAD)"
COMMIT_DATE="$(git show -s --format=%cI HEAD)"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "prev_tag=${PREV_TAG}" >> "$GITHUB_OUTPUT"
echo "range_start=${RANGE_START}" >> "$GITHUB_OUTPUT"
echo "range_end=${RANGE_END}" >> "$GITHUB_OUTPUT"
echo "commit_sha=${COMMIT_SHA}" >> "$GITHUB_OUTPUT"
echo "commit_date=${COMMIT_DATE}" >> "$GITHUB_OUTPUT"
- name: Build contributors list (names only)
id: contrib
shell: bash
run: |
set -euo pipefail
start="${{ steps.meta.outputs.range_start }}"
end="${{ steps.meta.outputs.range_end }}"
git shortlog -sn "${start}..${end}" > CONTRIBUTORS.txt || true
echo "contributors<<EOF" >> "$GITHUB_OUTPUT"
cat CONTRIBUTORS.txt >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
- name: Summarize commits (since previous tag)
id: commits
shell: bash
run: |
set -euo pipefail
start="${{ steps.meta.outputs.range_start }}"
end="${{ steps.meta.outputs.range_end }}"
{
echo "### Commits since ${start:0:20}"
echo
git log --no-merges --pretty=format:'- %h %ad %an: %s' --date=short "${start}..${end}" || true
echo
} > COMMITS.md
echo "commits<<EOF" >> "$GITHUB_OUTPUT"
cat COMMITS.md >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
- name: Artifact sizes table
id: sizes
shell: bash
run: |
set -euo pipefail
{
echo "| File | Size |"
echo "|------|------|"
for f in verge-windows32.zip verge-windows64.zip verge-macos15.zip verge-macos14.zip verge-ubuntu22.zip verge-ubuntu24.zip; do
if [ -f "$f" ]; then
sz=$(du -h "$f" | awk '{print $1}')
echo "| $f | $sz |"
fi
done
} > SIZES.md
echo "sizes<<EOF" >> "$GITHUB_OUTPUT"
cat SIZES.md >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
- name: Read SHA256SUMS into a variable
id: checksums
run: |
echo "SHA256SUMS<<EOF" >> $GITHUB_OUTPUT
cat SHA256SUMS.txt >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Compose RELEASE.md
shell: bash
run: |
set -euo pipefail
{
echo "# Verge Core ${TAG_NAME}"
echo
echo "**Commit:** ${{ steps.meta.outputs.commit_sha }} &nbsp;&nbsp; **Date:** ${{ steps.meta.outputs.commit_date }}"
if [ -n "${{ steps.meta.outputs.prev_tag }}" ]; then
echo "**Changes since:** ${{ steps.meta.outputs.prev_tag }}"
fi
echo
echo "## Downloads"
echo
cat SIZES.md
echo
echo "## SHA256 Checksums:"
echo
echo '```txt'
cat SHA256SUMS.txt
echo '```'
echo
echo "## Contributors:"
echo
if [ -s CONTRIBUTORS.txt ]; then
awk '{c=$1; $1=""; sub(/^ /,""); print "- " $0 " _(commits: " c ")_"}' CONTRIBUTORS.txt
else
echo "_No contributor deltas in this range_"
fi
echo
echo "## Commit Summary"
echo
cat COMMITS.md
echo
echo "## Notes"
echo "- elease artifacts are built via Github automated CI across Windows, macOS (Intel/Apple Silicon), and Linux."
echo "- Each artifact above is produced by Github automated CI from the exact commit listed, and can be verified with the SHA256 checksums."
} > RELEASE.md
sed -n '1,200p' RELEASE.md
- name: Push zips to release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.TAG_NAME }}
files: |
verge-windows32.zip
verge-windows64.zip
verge-macos15.zip
verge-macos14.zip
verge-ubuntu22.zip
verge-ubuntu24.zip
SHA256SUMS.txt
body_path: RELEASE.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}