@@ -150,9 +150,8 @@ jobs:
150150 # ---------------------------------------------------------------------------
151151 # Build CLI binaries (Linux musl — static, native on each arch)
152152 #
153- # Builds run directly on the CI host (glibc Ubuntu). The system g++ is
154- # used for C++ compilation (z3) with _FORTIFY_SOURCE disabled to avoid
155- # glibc-specific hardened symbols that do not exist in musl.
153+ # Builds run directly on the CI host (glibc Ubuntu). Zig provides musl
154+ # C/C++ toolchains for bundled-z3 and ring, and is also used as the linker.
156155 # ---------------------------------------------------------------------------
157156 build-cli-linux :
158157 name : Build CLI (Linux ${{ matrix.arch }})
@@ -163,9 +162,11 @@ jobs:
163162 - arch : amd64
164163 runner : build-amd64
165164 target : x86_64-unknown-linux-musl
165+ zig_target : x86_64-linux-musl
166166 - arch : arm64
167167 runner : build-arm64
168168 target : aarch64-unknown-linux-musl
169+ zig_target : aarch64-linux-musl
169170 runs-on : ${{ matrix.runner }}
170171 timeout-minutes : 60
171172 container :
@@ -202,27 +203,36 @@ jobs:
202203 - name : Add Rust musl target
203204 run : mise x -- rustup target add ${{ matrix.target }}
204205
205- - name : Set up musl C++ wrapper
206+ - name : Set up zig musl wrappers
206207 run : |
207208 set -euo pipefail
208- # System g++ with _FORTIFY_SOURCE disabled. FORTIFY_SOURCE makes
209- # g++ emit glibc-specific hardened calls (__printf_chk, __memcpy_chk)
210- # that do not exist in musl, causing linker failures. Disabling it
211- # produces standard POSIX calls that resolve against musl.
212- printf '#!/bin/sh\nexec g++ -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 "$@"\n' \
213- > /usr/local/bin/musl-g++
214- chmod +x /usr/local/bin/musl-g++
215-
216- # Point both CC and CXX at wrappers that disable _FORTIFY_SOURCE.
217- # CC must be set explicitly or cc-rs probes for aarch64-linux-musl-gcc
218- # which does not exist on the Ubuntu CI host.
219- printf '#!/bin/sh\nexec cc -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 "$@"\n' \
220- > /usr/local/bin/musl-cc
221- chmod +x /usr/local/bin/musl-cc
209+ ZIG="$(mise which zig)"
210+ ZIG_TARGET="${{ matrix.zig_target }}"
211+ mkdir -p /tmp/zig-musl
212+
213+ # cc-rs injects --target=<rust-triple> (for example
214+ # aarch64-unknown-linux-musl), which zig does not parse. Strip any
215+ # caller-provided --target and use the wrapper's zig-native target.
216+ for tool in cc c++; do
217+ printf '#!/bin/bash\nargs=()\nfor arg in "$@"; do\n case "$arg" in\n --target=*) ;;\n *) args+=("$arg") ;;\n esac\ndone\nexec "%s" %s --target=%s "${args[@]}"\n' \
218+ "$ZIG" "$tool" "$ZIG_TARGET" > "/tmp/zig-musl/${tool}"
219+ chmod +x "/tmp/zig-musl/${tool}"
220+ done
222221
223222 TARGET_ENV=$(echo "${{ matrix.target }}" | tr '-' '_')
224- echo "CC_${TARGET_ENV}=/usr/local/bin/musl-cc" >> "$GITHUB_ENV"
225- echo "CXX_${TARGET_ENV}=/usr/local/bin/musl-g++" >> "$GITHUB_ENV"
223+ TARGET_ENV_UPPER=${TARGET_ENV^^}
224+
225+ # Use zig for C/C++ compilation and final linking.
226+ echo "CC_${TARGET_ENV}=/tmp/zig-musl/cc" >> "$GITHUB_ENV"
227+ echo "CXX_${TARGET_ENV}=/tmp/zig-musl/c++" >> "$GITHUB_ENV"
228+ echo "CARGO_TARGET_${TARGET_ENV_UPPER}_LINKER=/tmp/zig-musl/cc" >> "$GITHUB_ENV"
229+
230+ # Let zig own CRT/startfiles to avoid duplicate _start symbols.
231+ echo "CARGO_TARGET_${TARGET_ENV_UPPER}_RUSTFLAGS=-Clink-self-contained=no" >> "$GITHUB_ENV"
232+
233+ # z3 built with zig c++ uses libc++ symbols (std::__1::*).
234+ # Override z3-sys default (stdc++) so Rust links the matching runtime.
235+ echo "CXXSTDLIB=c++" >> "$GITHUB_ENV"
226236
227237 - name : Scope workspace to CLI crates
228238 run : |
0 commit comments