11name : Makefile CI
2+
23on :
34 push :
45 branches : [ main, master ]
1415 # ═══════════════════════════════════════════════════════════════════
1516 # Linux builds — Alpine Docker for fully-static musl binaries
1617 #
17- # Alpine splits static libs into separate * -static packages.
18- # Every -l<foo> used at link time needs the corresponding .a file .
18+ # Alpine does NOT ship -static packages for spdlog / fmt / argon2,
19+ # so we build them from source inside the container .
1920 # ═══════════════════════════════════════════════════════════════════
2021 build-linux :
2122 runs-on : ubuntu-latest
@@ -50,89 +51,139 @@ jobs:
5051 sh -c '
5152 set -ex
5253
53- # ── Core build tools ──
54+ # ══════════════════════════════════════════════════════
55+ # 1. Build tools
56+ # ══════════════════════════════════════════════════════
5457 apk add --no-cache \
55- build-base make pkgconf linux-headers
58+ build-base make pkgconf cmake linux-headers \
59+ wget tar xz
5660
57- # ── Dev packages (headers + .so symlinks) ──
58- apk add --no-cache \
59- boost-dev \
60- spdlog-dev \
61- fmt-dev \
62- nlohmann-json \
63- openssl-dev \
64- curl-dev \
65- argon2-dev \
66- util-linux-dev \
67- zlib-dev \
68- brotli-dev \
69- nghttp2-dev \
70- zstd-dev
71-
72- # ── Matching -static packages (provides .a files) ──
73- # These are REQUIRED for -static linking on Alpine.
61+ # ══════════════════════════════════════════════════════
62+ # 2. Header-only libraries (from Alpine packages)
63+ # ══════════════════════════════════════════════════════
64+ apk add --no-cache boost-dev nlohmann-json
65+
66+ # ══════════════════════════════════════════════════════
67+ # 3. Libraries that DO have -static packages in Alpine
68+ # ══════════════════════════════════════════════════════
7469 apk add --no-cache \
75- openssl-libs-static \
76- curl-static \
77- zlib-static \
78- brotli-static \
79- nghttp2-static \
80- zstd-static \
81- spdlog-static \
82- fmt-static
83-
84- # ── Optional -static packages (may not exist on all Alpine versions) ──
85- # Each installed individually so a missing one does not block the rest.
70+ openssl-dev openssl-libs-static \
71+ curl-dev curl-static \
72+ zlib-dev zlib-static \
73+ brotli-dev brotli-static \
74+ nghttp2-dev nghttp2-static
75+
76+ # Optional transitive deps of libcurl (try each individually)
8677 for pkg in \
87- argon2-static \
88- util-linux-static \
78+ zstd-dev zstd-static \
8979 libpsl-dev libpsl-static \
9080 libidn2-dev libidn2-static \
9181 libunistring-dev libunistring-static \
9282 c-ares-dev c-ares-static
9383 do
94- apk add --no-cache "$pkg" 2>/dev/null || echo "SKIP (not found) : $pkg"
84+ apk add --no-cache "$pkg" 2>/dev/null || echo "SKIP: $pkg"
9585 done
9686
97- # ── Diagnostics ──
98- echo "===== pkg-config --static --libs libcurl ====="
99- pkg-config --static --libs libcurl || true
100- echo "===== pkg-config --static --libs spdlog ====="
101- pkg-config --static --libs spdlog || true
102- echo "===== Checking .a files ====="
103- ls /usr/lib/libspdlog.a /usr/lib/libfmt.a /usr/lib/libargon2.a /usr/lib/libuuid.a 2>&1 || true
104- ls /usr/lib/libcurl.a /usr/lib/libssl.a /usr/lib/libcrypto.a /usr/lib/libz.a 2>&1 || true
105-
106- # ── If argon2 static lib is still missing, build from source ──
107- if [ ! -f /usr/lib/libargon2.a ]; then
108- echo ">> Building libargon2.a from source"
109- cd /tmp
110- wget -q https://github.com/P-H-C/phc-winner-argon2/archive/refs/tags/20190702.tar.gz
111- tar xf 20190702.tar.gz && cd phc-winner-argon2-20190702
112- make -j$(nproc) LIBRARY_REL=lib ARGON2_BUILD_DIR=/usr install
113- cd /workspace
114- fi
87+ # ══════════════════════════════════════════════════════
88+ # 4. Build fmt from source (Alpine has NO fmt-static)
89+ # ══════════════════════════════════════════════════════
90+ cd /tmp
91+ wget -q https://github.com/fmtlib/fmt/archive/refs/tags/10.2.1.tar.gz -O fmt.tar.gz
92+ tar xf fmt.tar.gz && cd fmt-10.2.1
93+ cmake -B build \
94+ -DCMAKE_INSTALL_PREFIX=/usr \
95+ -DCMAKE_BUILD_TYPE=Release \
96+ -DBUILD_SHARED_LIBS=OFF \
97+ -DFMT_TEST=OFF \
98+ -DFMT_DOC=OFF
99+ cmake --build build -j$(nproc)
100+ cmake --install build
101+
102+ # ══════════════════════════════════════════════════════
103+ # 5. Build spdlog from source (Alpine has NO spdlog-static)
104+ # ══════════════════════════════════════════════════════
105+ cd /tmp
106+ wget -q https://github.com/gabime/spdlog/archive/refs/tags/v1.14.1.tar.gz -O spdlog.tar.gz
107+ tar xf spdlog.tar.gz && cd spdlog-1.14.1
108+ cmake -B build \
109+ -DCMAKE_INSTALL_PREFIX=/usr \
110+ -DCMAKE_BUILD_TYPE=Release \
111+ -DBUILD_SHARED_LIBS=OFF \
112+ -DSPDLOG_BUILD_EXAMPLE=OFF \
113+ -DSPDLOG_BUILD_TESTS=OFF \
114+ -DSPDLOG_FMT_EXTERNAL=ON
115+ cmake --build build -j$(nproc)
116+ cmake --install build
117+
118+ # ══════════════════════════════════════════════════════
119+ # 6. Build libargon2 from source (no -static package)
120+ # ══════════════════════════════════════════════════════
121+ cd /tmp
122+ wget -q https://github.com/P-H-C/phc-winner-argon2/archive/refs/tags/20190702.tar.gz -O argon2.tar.gz
123+ tar xf argon2.tar.gz && cd phc-winner-argon2-20190702
124+ cc -std=c89 -O2 -c src/argon2.c -Iinclude -o src/argon2.o
125+ cc -std=c89 -O2 -c src/core.c -Iinclude -o src/core.o
126+ cc -std=c89 -O2 -c src/blake2/blake2b.c -Iinclude -o src/blake2/blake2b.o
127+ cc -std=c89 -O2 -c src/thread.c -Iinclude -o src/thread.o
128+ cc -std=c89 -O2 -c src/encoding.c -Iinclude -o src/encoding.o
129+ cc -std=c89 -O2 -c src/ref.c -Iinclude -o src/ref.o
130+ ar rcs libargon2.a src/argon2.o src/core.o src/blake2/blake2b.o \
131+ src/thread.o src/encoding.o src/ref.o
132+ cp libargon2.a /usr/lib/
133+ cp include/argon2.h /usr/include/
134+ cat > /usr/lib/pkgconfig/libargon2.pc << PC
135+ prefix=/usr
136+ libdir=\${prefix}/lib
137+ includedir=\${prefix}/include
138+ Name: libargon2
139+ Description: Argon2 password hashing library
140+ Version: 20190702
141+ Libs: -L\${libdir} -largon2
142+ Cflags: -I\${includedir}
143+ PC
115144
116- # ── If libuuid static lib is still missing, build from source ──
145+ # ══════════════════════════════════════════════════════
146+ # 7. Build libuuid static if missing
147+ # ══════════════════════════════════════════════════════
148+ apk add --no-cache util-linux-dev 2>/dev/null || true
117149 if [ ! -f /usr/lib/libuuid.a ]; then
118150 echo ">> Building libuuid.a from source"
119151 cd /tmp
120- apk add --no-cache autoconf automake libtool gettext-dev
121- wget -q https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.40/util-linux-2.40.tar.xz
122- tar xf util-linux-2.40.tar.xz && cd util-linux-2.40
123- ./configure --disable-all-programs --enable-libuuid --enable-static --disable-shared --prefix=/usr
124- make -j$(nproc) && make install
125- cd /workspace
152+ apk add --no-cache autoconf automake libtool gettext-dev bison
153+ 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
154+ tar xf util-linux.tar.xz && cd util-linux-2.40.2
155+ ./configure --disable-all-programs --enable-libuuid \
156+ --enable-static --disable-shared --prefix=/usr
157+ make -j$(nproc)
158+ make install
126159 fi
127160
128- # ── Build the project ──
161+ # ══════════════════════════════════════════════════════
162+ # 8. Diagnostics
163+ # ══════════════════════════════════════════════════════
164+ echo "===== Verifying static libraries ====="
165+ for lib in spdlog fmt argon2 uuid curl ssl crypto z zstd brotlidec brotlicommon nghttp2; do
166+ [ -f /usr/lib/lib${lib}.a ] && echo "OK /usr/lib/lib${lib}.a" || echo "MISS /usr/lib/lib${lib}.a"
167+ done
168+
169+ echo "===== pkg-config --static --libs libcurl ====="
170+ pkg-config --static --libs libcurl 2>&1 || true
171+ echo "===== pkg-config --static --libs spdlog ====="
172+ pkg-config --static --libs spdlog 2>&1 || true
173+
174+ # ══════════════════════════════════════════════════════
175+ # 9. Build the project
176+ # ══════════════════════════════════════════════════════
177+ cd /workspace
129178 make clean
130179 make -j$(nproc) \
131180 STATIC=1 \
132181 LOCALES_DIR=\"./locales\" \
133182 TARGET=phira-mp-server
134183
135- # ── Verify ──
184+ # ══════════════════════════════════════════════════════
185+ # 10. Verify
186+ # ══════════════════════════════════════════════════════
136187 file phira-mp-server
137188 ls -lh phira-mp-server
138189 '
@@ -182,28 +233,33 @@ jobs:
182233
183234 - name : Install or build argon2
184235 run : |
185- # Try installing from MSYS2 repo first
186- pacman -S --noconfirm mingw-w64-ucrt-x86_64-argon2 2>/dev/null && exit 0
236+ # Try the MSYS2 package first
237+ pacman -S --noconfirm mingw-w64-ucrt-x86_64-argon2 2>/dev/null && {
238+ echo "argon2 installed from MSYS2 repo"
239+ exit 0
240+ }
187241
188- echo ">> argon2 not in repo, building from source"
242+ echo ">> Building argon2 from source for MinGW "
189243 cd /tmp
190244 curl -sL https://github.com/P-H-C/phc-winner-argon2/archive/refs/tags/20190702.tar.gz | tar xz
191245 cd phc-winner-argon2-20190702
192- gcc -std=c89 -O2 -c src/argon2.c -Iinclude -o src/argon2.o
193- gcc -std=c89 -O2 -c src/core.c -Iinclude -o src/core.o
246+ gcc -std=c89 -O2 -c src/argon2.c -Iinclude -o src/argon2.o
247+ gcc -std=c89 -O2 -c src/core.c -Iinclude -o src/core.o
194248 gcc -std=c89 -O2 -c src/blake2/blake2b.c -Iinclude -o src/blake2/blake2b.o
195- gcc -std=c89 -O2 -c src/thread.c -Iinclude -o src/thread.o
196- gcc -std=c89 -O2 -c src/encoding.c -Iinclude -o src/encoding.o
197- gcc -std=c89 -O2 -c src/ref.c -Iinclude -o src/ref.o
198- ar rcs libargon2.a src/argon2.o src/core.o src/blake2/blake2b.o src/thread.o src/encoding.o src/ref.o
249+ gcc -std=c89 -O2 -c src/thread.c -Iinclude -o src/thread.o
250+ gcc -std=c89 -O2 -c src/encoding.c -Iinclude -o src/encoding.o
251+ gcc -std=c89 -O2 -c src/ref.c -Iinclude -o src/ref.o
252+ ar rcs libargon2.a src/argon2.o src/core.o src/blake2/blake2b.o \
253+ src/thread.o src/encoding.o src/ref.o
199254 cp libargon2.a /ucrt64/lib/
200255 cp include/argon2.h /ucrt64/include/
201- # Create a pkg-config file
256+
257+ # Create pkg-config file so Makefile can find it
258+ mkdir -p /ucrt64/lib/pkgconfig
202259 cat > /ucrt64/lib/pkgconfig/libargon2.pc << 'PC'
203260 prefix=/ucrt64
204261 libdir=${prefix}/lib
205262 includedir=${prefix}/include
206-
207263 Name: libargon2
208264 Description: Argon2 password hashing library
209265 Version: 20190702
@@ -214,8 +270,6 @@ jobs:
214270 - name : Build
215271 run : |
216272 echo "===== pkg-config diagnostics ====="
217- pkg-config --list-all | grep -iE "argon|spdlog|curl|openssl|nlohmann" || true
218- echo "===== LIBS from pkg-config ====="
219273 pkg-config --libs spdlog libargon2 nlohmann_json openssl libcurl 2>&1 || true
220274
221275 make -j$(nproc) \
@@ -231,14 +285,15 @@ jobs:
231285
232286 cp phira-mp-server.exe release/phira-mp-server-windows-amd64/
233287
234- # Collect every UCRT64 DLL the exe depends on (recursively)
288+ # ── Recursively collect every UCRT64 DLL the exe needs ──
235289 collect_dlls() {
236290 local binary="$1"
237291 ldd "$binary" 2>/dev/null | grep -i '/ucrt64/' | awk '{print $3}' | while read -r dll; do
238- local base=$(basename "$dll")
292+ [ -z "$dll" ] && continue
293+ local base
294+ base=$(basename "$dll")
239295 if [ ! -f "release/phira-mp-server-windows-amd64/$base" ] && [ -f "$dll" ]; then
240296 cp "$dll" release/phira-mp-server-windows-amd64/
241- # Recurse to catch transitive dependencies
242297 collect_dlls "$dll"
243298 fi
244299 done
0 commit comments