Skip to content

Commit 2fbd552

Browse files
committed
ci(session-e2e): wrap zig in single-binary cgo launchers for Windows
The Windows link failed with 'fork/exec zig.exe: The filename or extension is too long' (Win error 206). The cgo build links ~560 object files whose paths overflow Windows' command-line limit. Go writes link args to a @response file when they're too long, but only after probing that the linker accepts @file -- and that probe runs only argv[0] of $CC. With CC="zig cc -target ...", argv[0] is bare 'zig' (no 'cc' subcommand), so the probe fails, Go skips the response file, and the argv overflows. Build zcc.exe/zxx.exe launchers that forward to 'zig cc'/'zig c++' so $CC is a single executable, the probe passes, and Go uses a response file.
1 parent ade2937 commit 2fbd552

1 file changed

Lines changed: 48 additions & 7 deletions

File tree

.github/workflows/session-e2e.yaml

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,60 @@ jobs:
6868
with:
6969
version: 0.14.1
7070

71-
- name: Use Zig as cgo compiler (Windows)
72-
if: matrix.os == 'windows-latest'
73-
shell: bash
74-
run: |
75-
echo "CC=zig cc -target x86_64-windows-gnu" >> "$GITHUB_ENV"
76-
echo "CXX=zig c++ -target x86_64-windows-gnu" >> "$GITHUB_ENV"
77-
7871
- name: Set up Go
7972
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
8073
with:
8174
go-version-file: go.mod
8275
cache: true
8376

77+
# Wrap `zig cc`/`zig c++` in single-binary launchers and point CC/CXX at
78+
# them. Why not CC="zig cc -target ..." directly: the cgo build links ~560
79+
# object files (webrtc APM + portaudio), whose paths overflow Windows'
80+
# ~32KB command-line limit ("fork/exec zig.exe: The filename or extension
81+
# is too long"). Go's linker avoids this by writing the args to a @response
82+
# file, but only after probing that the linker accepts one -- and the probe
83+
# runs only argv[0] of $CC. With a multi-token CC that's bare `zig` (no
84+
# `cc` subcommand), so the probe fails, Go skips the response file, and the
85+
# full argv overflows. A single-binary CC makes the probe pass. Must run
86+
# after Set up Go (it builds the launchers) and before any cgo build.
87+
- name: Build zig cgo launchers (Windows)
88+
if: matrix.os == 'windows-latest'
89+
shell: bash
90+
run: |
91+
dir="$(cygpath "$RUNNER_TEMP")/zigcc"
92+
mkdir -p "$dir"
93+
cat > "$dir/main.go" <<'EOF'
94+
// Forwards to `zig cc`/`zig c++ -target x86_64-windows-gnu`, picking the
95+
// subcommand from its own basename, so $CC/$CXX are single executables.
96+
package main
97+
98+
import (
99+
"os"
100+
"os/exec"
101+
"path/filepath"
102+
"strings"
103+
)
104+
105+
func main() {
106+
sub := "cc"
107+
if b := filepath.Base(os.Args[0]); strings.Contains(b, "xx") || strings.Contains(b, "++") {
108+
sub = "c++"
109+
}
110+
cmd := exec.Command("zig", append([]string{sub, "-target", "x86_64-windows-gnu"}, os.Args[1:]...)...)
111+
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
112+
if err := cmd.Run(); err != nil {
113+
if ee, ok := err.(*exec.ExitError); ok {
114+
os.Exit(ee.ExitCode())
115+
}
116+
os.Exit(1)
117+
}
118+
}
119+
EOF
120+
(cd "$dir" && go mod init zigcc && go build -o zcc.exe . && go build -o zxx.exe .)
121+
win="$(cygpath -w "$dir")"
122+
echo "CC=$win\\zcc.exe" >> "$GITHUB_ENV"
123+
echo "CXX=$win\\zxx.exe" >> "$GITHUB_ENV"
124+
84125
- name: Set up Python
85126
uses: actions/setup-python@v5
86127
with:

0 commit comments

Comments
 (0)