Skip to content

Windows Build (MinGW64) #94

Windows Build (MinGW64)

Windows Build (MinGW64) #94

Workflow file for this run

name: Windows Build (MinGW64)
# Builds interchainedd.exe on Windows via MSYS2 MinGW64.
# BDB comes from the MSYS2 package (mingw-w64-x86_64-db) — no from-source
# build needed; the MSYS2 package ships Windows-patched headers and static
# libs at /mingw64/{include,lib}. --with-incompatible-bdb handles the
# version mismatch vs 4.8.
on:
workflow_dispatch:
permissions:
contents: write
jobs:
windows-x86_64:
name: Windows x86_64 — interchainedd.exe
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up MSYS2 (MinGW64)
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
git
make
autoconf
automake
libtool
pkg-config
mingw-w64-x86_64-gcc
mingw-w64-x86_64-boost
mingw-w64-x86_64-libevent
mingw-w64-x86_64-sqlite3
mingw-w64-x86_64-zeromq
mingw-w64-x86_64-miniupnpc
mingw-w64-x86_64-openssl
mingw-w64-x86_64-zlib
mingw-w64-x86_64-db
perl
- name: Verify BDB and Boost from MSYS2
run: |
echo "=== BDB headers ==="
ls -lah /mingw64/include/db*.h
echo "=== BDB libs ==="
ls -lah /mingw64/lib/libdb*.a /mingw64/lib/libdb*.dll.a 2>/dev/null || true
echo "=== BDB version ==="
grep DB_VERSION_STRING /mingw64/include/db.h | head -3
echo "=== Boost static libs ==="
ls /mingw64/lib/libboost_*.a 2>/dev/null | sort
- name: Install Rust stable + x86_64-pc-windows-gnu target
shell: pwsh
run: |
# Install rustup + stable toolchain (idempotent)
$env:RUSTUP_INIT_SKIP_PATH_CHECK = "yes"
Invoke-WebRequest "https://win.rustup.rs/x86_64" -OutFile "$env:TEMP\rustup-init.exe"
& "$env:TEMP\rustup-init.exe" -y --default-toolchain stable --profile minimal 2>&1
$env:PATH = "$env:USERPROFILE\.cargo\bin;$env:PATH"
rustup target add x86_64-pc-windows-gnu
Write-Host "Rust: $(rustc --version)"
Write-Host "Cargo: $(cargo --version)"
- name: Build NEDB FFI (x86_64-pc-windows-gnu)
run: |
export PATH="$(cygpath "$USERPROFILE")/.cargo/bin:$PATH"
sed -i 's/^lto[[:space:]]*=.*/lto = false/' nedb-ffi/Cargo.toml
cd nedb-ffi
RUSTFLAGS="-C embed-bitcode=no" \
cargo rustc --release --crate-type=staticlib \
--target x86_64-pc-windows-gnu
echo "libnedb_ffi.a size: $(du -sh target/x86_64-pc-windows-gnu/release/libnedb_ffi.a | cut -f1)"
# Windows PE/COFF 64-bit symbols have no leading underscore — grep without it
SYMS=$(nm target/x86_64-pc-windows-gnu/release/libnedb_ffi.a 2>/dev/null \
| grep -c 'nedb_' || true)
echo "nedb_* symbols: $SYMS"
[ "${SYMS:-0}" -gt 0 ] || { echo "ERROR: no nedb_* symbols found"; exit 1; }
- name: Stage NEDB FFI .la at native release path
run: |
NEDB_X64="$(pwd)/nedb-ffi/target/x86_64-pc-windows-gnu/release/libnedb_ffi.a"
NEDB_NATIVE_DIR="$(pwd)/nedb-ffi/target/release"
mkdir -p "$NEDB_NATIVE_DIR"
cp "$NEDB_X64" "$NEDB_NATIVE_DIR/libnedb_ffi.a"
printf '%s\n' \
"# Generated by libtool (GNU libtool) 2.4.6" \
"dlname=''" \
"library_names=''" \
"old_library='libnedb_ffi.a'" \
"inherited_linker_flags=''" \
"dependency_libs='-lpthread -lws2_32 -lbcrypt -lntdll'" \
"weak_library_names=''" \
"current=0" "age=0" "revision=0" \
"installed=no" "shouldnotlink=no" \
"dlopen=''" "dlpreopen=''" \
"libdir='$NEDB_NATIVE_DIR'" \
> "$NEDB_NATIVE_DIR/libnedb_ffi.la"
echo "Staged: $NEDB_NATIVE_DIR/libnedb_ffi.la"
cat "$NEDB_NATIVE_DIR/libnedb_ffi.la"
- name: Configure & Build interchainedd.exe
run: |
export PATH="$(cygpath "$USERPROFILE")/.cargo/bin:$PATH"
J=$(nproc || echo 4)
# Use BDB from MSYS2 package — headers and static libs at /mingw64
BDB_PREFIX="/mingw64"
./autogen.sh
# Boost 1.74+ / MSYS2 MinGW64: the AX_BOOST_* macros have a two-step
# guard in the generated configure:
# 1) "Could not find a version" — fires when ax_lib="" (ls glob empty)
# 2) "Could not link against $ax_lib !" — fires when link_X != yes
# We patch step-1 to set ax_lib + link_X=yes + BOOST_X_LIB, and
# neutralise step-2 entirely. The real .a files are at /mingw64/lib
# and will be linked at make time via BOOST_LIBS.
# Boost 1.91 MSYS2 MinGW64 quirks:
# - boost::system is fully header-only (no libboost_system.a shipped)
# → BOOST_SYSTEM_LIB must be empty or the linker errors
# - boost::filesystem and boost::thread DO have static libs
# Patch both AX_BOOST_* guards (find + link) for each library.
# MSYS2 MinGW64 Boost 1.91: static libs use -mt suffix
# (e.g. libboost_filesystem-mt.a, libboost_thread-mt.a).
# boost::system is fully header-only — no lib file at all.
sed -i \
-e 's/as_fn_error.*Could not find a version of the Boost::System library.*/ax_lib=; link_system=yes; BOOST_SYSTEM_LIB=""/' \
-e 's/as_fn_error.*Could not find a version of the Boost::Filesystem library.*/ax_lib=boost_filesystem-mt; link_filesystem=yes; BOOST_FILESYSTEM_LIB="-lboost_filesystem-mt"/' \
-e 's/as_fn_error.*Could not find a version of the Boost::Thread library.*/ax_lib=boost_thread-mt; link_thread=yes; BOOST_THREAD_LIB="-lboost_thread-mt"/' \
-e 's/as_fn_error.*Could not find a version of the Boost::Chrono library.*/ax_lib=boost_chrono-mt; link_chrono=yes; BOOST_CHRONO_LIB="-lboost_chrono-mt"/' \
-e 's/as_fn_error.*Could not link against \$ax_lib.*/true # MinGW64 Boost link-test bypassed/' \
configure
# Use versioned static archives — the unversioned libdb.a / libdb_cxx.a
# are thin import libs (DLL stubs, ~1MB). The full static archives are
# libdb-6.2.a / libdb_cxx-6.2.a (~2-2.5MB). Pass as direct paths so
# the configure link test picks up real code, not the DLL shims.
BDB_CFLAGS="-I${BDB_PREFIX}/include" \
BDB_LIBS="${BDB_PREFIX}/lib/libdb_cxx-6.2.a ${BDB_PREFIX}/lib/libdb-6.2.a" \
./configure \
--enable-wallet \
--with-incompatible-bdb \
--without-gui \
--disable-bench \
--disable-tests \
--without-zmq \
--without-miniupnpc \
|| { cat config.log; exit 1; }
# Scope NEDB + its Windows deps to interchainedd only.
# Using LIBS += injects NEDB into every target (cli, tx, etc.) which
# then all need to satisfy Rust stdlib Windows API deps — unnecessary
# and fragile. interchainedd_LDADD targets just the daemon binary.
#
# --allow-multiple-definition: Rust staticlib bundles Windows API
# import stubs that conflict with MinGW's own stubs.
# -lbcrypt: BCryptGenRandom (Rust getrandom crate)
# -lntdll: NtCreateNamedPipeFile (Rust std process pipes)
# -luserenv: GetUserProfileDirectoryW (Rust std home dir)
# -lsodium: libzmq CURVE support
#
# Boost is still in LIBS so cli/tx/wallet can find it.
NEDB_LIB="$(pwd)/nedb-ffi/target/release/libnedb_ffi.a"
# --whole-archive only on interchainedd (force-load all NEDB symbols).
# Windows API deps go in LIBS so every NEDB-linked target gets them
# (interchainedd + interchained-wallet both link libnedb_ffi).
echo "interchainedd_LDADD += -Wl,--allow-multiple-definition -Wl,--whole-archive,${NEDB_LIB},--no-whole-archive" \
>> src/Makefile
# -lntdll removed: explicit ntdll import causes Windows to eagerly resolve
# ntdll's own kernel deps (ksecdd.sys) at load time — "ksecdd.sys not found".
# ntdll is always implicitly loaded; never link it explicitly.
echo "LIBS += -lboost_thread-mt -lboost_chrono-mt -lboost_filesystem-mt -lws2_32 -lbcrypt -luserenv -lsodium" \
>> src/Makefile
make -j"$J" src/interchainedd.exe src/interchained-cli.exe
test -f src/interchainedd.exe && file src/interchainedd.exe
test -f src/interchained-cli.exe && file src/interchained-cli.exe
- name: Package Windows binary
run: |
REF="${GITHUB_REF_NAME:-${GITHUB_SHA:0:8}}"
mkdir -p out
cp src/interchainedd.exe out/ 2>/dev/null || true
cp src/interchained-cli.exe out/ 2>/dev/null || true
[ -f README.md ] && cp README.md out/ || true
sha256sum out/* > out/SHA256SUMS
tar -C out -czf "interchained-windows-x86_64-${REF}.tar.gz" .
echo "Binary size: $(du -sh out/interchainedd.exe 2>/dev/null || echo 'not found')"
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: interchained-windows-x86_64
path: interchained-windows-x86_64-*.tar.gz
if-no-files-found: error