Skip to content

fix

fix #20

Workflow file for this run

name: Makefile CI
on:
push:
branches: [ main, master ]
tags: [ 'v*' ]
pull_request:
branches: [ main, master ]
workflow_dispatch:
permissions:
contents: write
jobs:
# ═══════════════════════════════════════════════════════════════════
# Linux builds — Alpine Docker for fully-static musl binaries
#
# Alpine does NOT ship -static packages for spdlog / fmt / argon2,
# so we build them from source inside the container.
# ═══════════════════════════════════════════════════════════════════
build-linux:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
platform: linux/amd64
artifact: phira-mp-server-linux-amd64
- arch: arm64
platform: linux/arm64
artifact: phira-mp-server-linux-arm64
- arch: armhf
platform: linux/arm/v7
artifact: phira-mp-server-linux-armhf
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU (for cross-architecture builds)
if: matrix.arch != 'amd64'
uses: docker/setup-qemu-action@v3
- name: Build static binary in Alpine container
run: |
docker run --rm --platform ${{ matrix.platform }} \
-v "${{ github.workspace }}:/workspace" \
-w /workspace \
alpine:3.21 \
sh -c '
set -ex
# ══════════════════════════════════════════════════════
# 1. Build tools
# ══════════════════════════════════════════════════════
apk add --no-cache \
build-base make pkgconf cmake linux-headers \
wget tar xz
# ══════════════════════════════════════════════════════
# 2. Header-only libraries (from Alpine packages)
# ══════════════════════════════════════════════════════
apk add --no-cache boost-dev nlohmann-json
# ══════════════════════════════════════════════════════
# 3. Libraries that DO have -static packages in Alpine
# ══════════════════════════════════════════════════════
apk add --no-cache \
openssl-dev openssl-libs-static \
curl-dev curl-static \
zlib-dev zlib-static \
brotli-dev brotli-static \
nghttp2-dev nghttp2-static
# Optional transitive deps of libcurl (try each individually)
for pkg in \
zstd-dev zstd-static \
libpsl-dev libpsl-static \
libidn2-dev libidn2-static \
libunistring-dev libunistring-static \
c-ares-dev c-ares-static
do
apk add --no-cache "$pkg" 2>/dev/null || echo "SKIP: $pkg"
done
# ══════════════════════════════════════════════════════
# 4. Build fmt from source (Alpine has NO fmt-static)
# ══════════════════════════════════════════════════════
cd /tmp
wget -q https://github.com/fmtlib/fmt/archive/refs/tags/10.2.1.tar.gz -O fmt.tar.gz
tar xf fmt.tar.gz && cd fmt-10.2.1
cmake -B build \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=OFF \
-DFMT_TEST=OFF \
-DFMT_DOC=OFF
cmake --build build -j$(nproc)
cmake --install build
# ══════════════════════════════════════════════════════
# 5. Build spdlog from source (Alpine has NO spdlog-static)
# ══════════════════════════════════════════════════════
cd /tmp
wget -q https://github.com/gabime/spdlog/archive/refs/tags/v1.14.1.tar.gz -O spdlog.tar.gz
tar xf spdlog.tar.gz && cd spdlog-1.14.1
cmake -B build \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=OFF \
-DSPDLOG_BUILD_EXAMPLE=OFF \
-DSPDLOG_BUILD_TESTS=OFF \
-DSPDLOG_FMT_EXTERNAL=ON
cmake --build build -j$(nproc)
cmake --install build
# ══════════════════════════════════════════════════════
# 6. Build libargon2 from source (no -static package)
# ══════════════════════════════════════════════════════
cd /tmp
wget -q https://github.com/P-H-C/phc-winner-argon2/archive/refs/tags/20190702.tar.gz -O argon2.tar.gz
tar xf argon2.tar.gz && cd phc-winner-argon2-20190702
cc -std=c89 -O2 -c src/argon2.c -Iinclude -o src/argon2.o
cc -std=c89 -O2 -c src/core.c -Iinclude -o src/core.o
cc -std=c89 -O2 -c src/blake2/blake2b.c -Iinclude -o src/blake2/blake2b.o
cc -std=c89 -O2 -c src/thread.c -Iinclude -o src/thread.o
cc -std=c89 -O2 -c src/encoding.c -Iinclude -o src/encoding.o
cc -std=c89 -O2 -c src/ref.c -Iinclude -o src/ref.o
ar rcs libargon2.a src/argon2.o src/core.o src/blake2/blake2b.o \
src/thread.o src/encoding.o src/ref.o
cp libargon2.a /usr/lib/
cp include/argon2.h /usr/include/
cat > /usr/lib/pkgconfig/libargon2.pc << PC
prefix=/usr
libdir=\${prefix}/lib
includedir=\${prefix}/include
Name: libargon2
Description: Argon2 password hashing library
Version: 20190702
Libs: -L\${libdir} -largon2
Cflags: -I\${includedir}
PC
# ══════════════════════════════════════════════════════
# 7. Build libuuid static if missing
# ══════════════════════════════════════════════════════
apk add --no-cache util-linux-dev 2>/dev/null || true
if [ ! -f /usr/lib/libuuid.a ]; then
echo ">> Building libuuid.a from source"
cd /tmp
apk add --no-cache autoconf automake libtool gettext-dev bison
wget -q https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.40/util-linux-2.40.2.tar.xz -O util-linux.tar.xz
tar xf util-linux.tar.xz && cd util-linux-2.40.2
./configure --disable-all-programs --enable-libuuid \
--enable-static --disable-shared --prefix=/usr
make -j$(nproc)
make install
fi
# ══════════════════════════════════════════════════════
# 8. Diagnostics
# ══════════════════════════════════════════════════════
echo "===== Verifying static libraries ====="
for lib in spdlog fmt argon2 uuid curl ssl crypto z zstd brotlidec brotlicommon nghttp2; do
[ -f /usr/lib/lib${lib}.a ] && echo "OK /usr/lib/lib${lib}.a" || echo "MISS /usr/lib/lib${lib}.a"
done
echo "===== pkg-config --static --libs libcurl ====="
pkg-config --static --libs libcurl 2>&1 || true
echo "===== pkg-config --static --libs spdlog ====="
pkg-config --static --libs spdlog 2>&1 || true
# ══════════════════════════════════════════════════════
# 9. Build the project
# ══════════════════════════════════════════════════════
cd /workspace
make clean
make -j$(nproc) \
STATIC=1 \
LOCALES_DIR=\"./locales\" \
TARGET=phira-mp-server
# ══════════════════════════════════════════════════════
# 10. Verify
# ══════════════════════════════════════════════════════
file phira-mp-server
ls -lh phira-mp-server
'
- name: Package artifact
run: |
mkdir -p release/${{ matrix.artifact }}
cp phira-mp-server release/${{ matrix.artifact }}/
cp -r locales release/${{ matrix.artifact }}/
cd release
tar czf ${{ matrix.artifact }}.tar.gz ${{ matrix.artifact }}/
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: release/${{ matrix.artifact }}.tar.gz
# ═══════════════════════════════════════════════════════════════════
# Windows amd64 — MSYS2 UCRT64, dynamic linking, bundle DLLs
# ═══════════════════════════════════════════════════════════════════
build-windows:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: UCRT64
update: true
install: >-
make
pkgconf
mingw-w64-ucrt-x86_64-gcc
mingw-w64-ucrt-x86_64-boost
mingw-w64-ucrt-x86_64-spdlog
mingw-w64-ucrt-x86_64-fmt
mingw-w64-ucrt-x86_64-nlohmann-json
mingw-w64-ucrt-x86_64-curl
mingw-w64-ucrt-x86_64-openssl
- name: Install or build argon2
run: |
# Try the MSYS2 package first
pacman -S --noconfirm mingw-w64-ucrt-x86_64-argon2 2>/dev/null && {
echo "argon2 installed from MSYS2 repo"
exit 0
}
echo ">> Building argon2 from source for MinGW"
cd /tmp
curl -sL https://github.com/P-H-C/phc-winner-argon2/archive/refs/tags/20190702.tar.gz | tar xz
cd phc-winner-argon2-20190702
gcc -std=c89 -O2 -c src/argon2.c -Iinclude -o src/argon2.o
gcc -std=c89 -O2 -c src/core.c -Iinclude -o src/core.o
gcc -std=c89 -O2 -c src/blake2/blake2b.c -Iinclude -o src/blake2/blake2b.o
gcc -std=c89 -O2 -c src/thread.c -Iinclude -o src/thread.o
gcc -std=c89 -O2 -c src/encoding.c -Iinclude -o src/encoding.o
gcc -std=c89 -O2 -c src/ref.c -Iinclude -o src/ref.o
ar rcs libargon2.a src/argon2.o src/core.o src/blake2/blake2b.o \
src/thread.o src/encoding.o src/ref.o
cp libargon2.a /ucrt64/lib/
cp include/argon2.h /ucrt64/include/
# Create pkg-config file so Makefile can find it
mkdir -p /ucrt64/lib/pkgconfig
cat > /ucrt64/lib/pkgconfig/libargon2.pc << 'PC'
prefix=/ucrt64
libdir=${prefix}/lib
includedir=${prefix}/include
Name: libargon2
Description: Argon2 password hashing library
Version: 20190702
Libs: -L${libdir} -largon2
Cflags: -I${includedir}
PC
- name: Build
run: |
echo "===== pkg-config diagnostics ====="
pkg-config --libs spdlog libargon2 nlohmann_json openssl libcurl 2>&1 || true
make -j$(nproc) \
TARGET=phira-mp-server.exe \
LOCALES_DIR=\"./locales\"
file phira-mp-server.exe
ls -lh phira-mp-server.exe
- name: Collect DLLs and package
run: |
mkdir -p release/phira-mp-server-windows-amd64
cp phira-mp-server.exe release/phira-mp-server-windows-amd64/
# ── Recursively collect every UCRT64 DLL the exe needs ──
collect_dlls() {
local binary="$1"
ldd "$binary" 2>/dev/null | grep -i '/ucrt64/' | awk '{print $3}' | while read -r dll; do
[ -z "$dll" ] && continue
local base
base=$(basename "$dll")
if [ ! -f "release/phira-mp-server-windows-amd64/$base" ] && [ -f "$dll" ]; then
cp "$dll" release/phira-mp-server-windows-amd64/
collect_dlls "$dll"
fi
done
}
collect_dlls phira-mp-server.exe
cp -r locales release/phira-mp-server-windows-amd64/
echo "===== Package contents ====="
ls -la release/phira-mp-server-windows-amd64/
- name: Create zip
shell: pwsh
run: |
Compress-Archive -Path release/phira-mp-server-windows-amd64 -DestinationPath release/phira-mp-server-windows-amd64.zip
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: phira-mp-server-windows-amd64
path: release/phira-mp-server-windows-amd64.zip
# ═══════════════════════════════════════════════════════════════════
# Release — create GitHub Release when a tag is pushed
# ═══════════════════════════════════════════════════════════════════
release:
needs: [build-linux, build-windows]
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: List artifacts
run: find artifacts -type f | sort
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: |
artifacts/phira-mp-server-linux-amd64/*.tar.gz
artifacts/phira-mp-server-linux-arm64/*.tar.gz
artifacts/phira-mp-server-linux-armhf/*.tar.gz
artifacts/phira-mp-server-windows-amd64/*.zip
generate_release_notes: true
draft: false
prerelease: false