Skip to content

windows: support reproducible native and cross toolchains (R7, depends on #2418) - #2422

Open
cpunion wants to merge 181 commits into
xgo-dev:mainfrom
cpunion:codex/windows-r7-on-r6-integration-20260826
Open

windows: support reproducible native and cross toolchains (R7, depends on #2418)#2422
cpunion wants to merge 181 commits into
xgo-dev:mainfrom
cpunion:codex/windows-r7-on-r6-integration-20260826

Conversation

@cpunion

@cpunion cpunion commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Depends on #2418.

Part of #2325.

Summary

  • make cross-compilation fixtures, archive creation, and ESP tooling portable on Windows
  • download and extract the official ESP Clang Windows archive
  • select Windows embedded compilers and Xtensa multilibs from the requested target
  • resolve MSYS2 import libraries for the MSVC linker
  • expose the required Windows SDK tools and resolve executable suffixes through PATHEXT

Dependency

This R7 change is stacked on R6 so the toolchain paths are exercised with the Windows runtime and standard-library support from #2418. The R7-only diff is 19 files with 536 additions and 123 deletions.

Validation

  • the final review-follow-up head passed all 43 checks across Linux, macOS, and Windows, including both Intel and arm64 macOS artifact jobs
  • Codecov patch coverage is 95.37%; the coverage follow-up raised it from 93.88%, and the patch gate passes
  • all 12 Linux/macOS benchmark program file-size and text-size results exactly match windows: integrate OS and standard-library support (R6, depends on #2405) #2418, so R7 adds no native artifact-size overhead beyond its R6 dependency
  • the R7 staging PR windows: validate reproducible toolchains against R6 (R7 integration) cpunion/llgo#189 passed its complete Linux, macOS, and Windows matrix before the coverage-only R6 follow-up
  • the R7-only patch at c96adb17a has SHA-256 b66b05e67ccf084073829486df44a1debc194f3e2584b8e3a4270b747fad8580
  • GOMAXPROCS=2 go test -count=1 -p=2 -timeout=20m ./internal/clang ./internal/crosscompile/... ./xtool/env/...
  • GOMAXPROCS=2 go test -count=1 -p=2 -run '^$' -timeout=10m ./internal/clite/ffi from the runtime module
  • git diff --check

The contribution head reruns the full CI matrix after each dependency update.

cpunion added 30 commits August 25, 2026 21:20
Provide direct Unix and Win32 thread, TLS, synchronization, atomic, stdio, setjmp, libuv, and OS adapters. Keep target-specific libraries and layouts isolated so Windows support does not add code to existing Unix binaries.
Lower PE/COFF dynamic imports, align the UCRT setjmp ABI, terminate through runtime.exit, and keep LLGO_ROOT/module parsing portable across CRLF checkouts. Cover the compiler paths and malformed target flags.
Select the hosted thread, synchronization, and atomic backends; add Windows process, clock, syscall, GC, setjmp, and lifecycle adapters; and retain the existing Unix behavior behind target-specific files. Reuse the Go Windows syscall wrapper surface and isolate Win32 code from other targets.
Implement syscall.NewCallback with cached libffi closures, Go-compatible signature validation, closure-identity keys, and 386 calling conventions. Route both syscall and reflect callbacks through the retained foreign-thread GC lifecycle so repeated callbacks avoid collector registration churn.
Run native PE/COFF runtime, FFI, GC, callback, thread, clock, import, and compiler-path smoke tests under the shared dependency setup. Keep the empty-program import audit alongside the feature tests so unintended runtime dependencies stay visible.
@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

LLGo baseline benchmarks

09a23ef5aa34 | workflow run | long-term charts

Program measurements

Platform Workload File size vs base Text size vs base Build vs base Run vs base
Linux cprintf 19432 B +176 B / +0.9% (worse) 387 B 0 B / +0.0% 306.504 ms +11.38 ms / +3.9% (worse) 1.006 ms +7.778 us / +0.8% (worse)
Linux cprintf-lto 19264 B +176 B / +0.9% (worse) 368 B 0 B / +0.0% 305.269 ms +10.61 ms / +3.6% (worse) 1.074 ms +60.69 us / +6.0% (worse)
Linux fmtprintf 1652152 B -1080 B / -0.1% (better) 501874 B +791 B / +0.2% (worse) 2.660 s +15.73 ms / +0.6% (worse) 2.896 ms +38.22 us / +1.3% (worse)
Linux fmtprintf-lto 1524104 B -1720 B / -0.1% (better) 460334 B +634 B / +0.1% (worse) 8.333 s -6.175 ms / -0.1% (better) 2.673 ms -61.79 us / -2.3% (better)
Linux println 62264 B +232 B / +0.4% (worse) 15286 B +25 B / +0.2% (worse) 300.544 ms -11.46 ms / -3.7% (better) 1.395 ms +62.51 us / +4.7% (worse)
Linux println-lto 54096 B +256 B / +0.5% (worse) 12914 B +32 B / +0.2% (worse) 466.747 ms -2.776 ms / -0.6% (better) 1.364 ms +22.99 us / +1.7% (worse)
macOS cprintf 84480 B 0 B / +0.0% 16669 B +176 B / +1.1% (worse) 348.563 ms +18.21 ms / +5.5% (worse) 2.232 ms -32.5 us / -1.4% (better)
macOS cprintf-lto 100704 B 0 B / +0.0% 16649 B +176 B / +1.1% (worse) 355.226 ms +12.42 ms / +3.6% (worse) 2.135 ms -137.5 us / -6.0% (better)
macOS fmtprintf 1512800 B +14544 B / +1.0% (worse) 882808 B +675 B / +0.1% (worse) 2.701 s +363.5 ms / +15.6% (worse) 8.488 ms +3.621 ms / +74.4% (worse)
macOS fmtprintf-lto 1208464 B -512 B / -0.04235% (better) 875848 B +719 B / +0.1% (worse) 6.449 s -315.3 ms / -4.7% (better) 4.819 ms -1.374 ms / -22.2% (better)
macOS println 114784 B -48 B / -0.0418% (better) 35101 B +252 B / +0.7% (worse) 379.649 ms +9.953 ms / +2.7% (worse) 6.709 ms +2.745 ms / +69.2% (worse)
macOS println-lto 118656 B 0 B / +0.0% 32753 B +264 B / +0.8% (worse) 603.069 ms +65.65 ms / +12.2% (worse) 2.932 ms -176.4 us / -5.7% (better)
Core language and compiler benchmarks
Platform Benchmark ns/op vs base
Linux BenchmarkLookupPCRandom 11.250 ns/op +0.1 ns/op / +0.9% (worse)
Linux BenchmarkMergeCompilerFlags 135.700 ns/op -3.5 ns/op / -2.5% (better)
Linux BenchmarkMergeLinkerFlags 92.800 ns/op -0.33 ns/op / -0.4% (better)
Linux BenchmarkChannelBuffered 57.090 ns/op -0.26 ns/op / -0.5% (better)
Linux BenchmarkChannelHandoff 29511 ns/op +1036 ns/op / +3.6% (worse)
Linux BenchmarkDefer 44.670 ns/op +0.03 ns/op / +0.1% (worse)
Linux BenchmarkDirectCall 1.301 ns/op -0.079 ns/op / -5.7% (better)
Linux BenchmarkGlobalRead 1.290 ns/op -0.124 ns/op / -8.8% (better)
Linux BenchmarkGlobalWrite 8.409 ns/op +0.022 ns/op / +0.3% (worse)
Linux BenchmarkGoroutine 32000 ns/op -4502 ns/op / -12.3% (better)
Linux BenchmarkInterfaceCall 6.466 ns/op -0.635 ns/op / -8.9% (better)
Linux BenchmarkRuntimeGetG 1.587 ns/op +0.154 ns/op / +10.7% (worse)
macOS BenchmarkLookupPCRandom 12.370 ns/op +0.47 ns/op / +3.9% (worse)
macOS BenchmarkMergeCompilerFlags 161.100 ns/op +33.7 ns/op / +26.5% (worse)
macOS BenchmarkMergeLinkerFlags 85.260 ns/op +12.06 ns/op / +16.5% (worse)
macOS BenchmarkChannelBuffered 25.160 ns/op +2.64 ns/op / +11.7% (worse)
macOS BenchmarkChannelHandoff 9167 ns/op +2210 ns/op / +31.8% (worse)
macOS BenchmarkDefer 32.650 ns/op +1.32 ns/op / +4.2% (worse)
macOS BenchmarkDirectCall 1.055 ns/op +0.0687 ns/op / +7.0% (worse)
macOS BenchmarkGlobalRead 1.051 ns/op +0.016 ns/op / +1.5% (worse)
macOS BenchmarkGlobalWrite 1.103 ns/op +0.094 ns/op / +9.3% (worse)
macOS BenchmarkGoroutine 26350 ns/op -652 ns/op / -2.4% (better)
macOS BenchmarkInterfaceCall 4.626 ns/op +0.139 ns/op / +3.1% (worse)
macOS BenchmarkRuntimeGetG 2.723 ns/op +0.798 ns/op / +41.5% (worse)

Compared with 6fe8babd468c measured in the same runner job.

@cpunion
cpunion marked this pull request as ready for review August 26, 2026 11:59
@cpunion

cpunion commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator Author

@fennoai /review

Please focus on the R7-only range b0676768c..af46044fa (18 files, +479/-120). The stacked R6 dependency is #2418 and has already completed its separate review.

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FennoAI Review — Windows toolchain support (R7)

Reviewed the R7-only range b0676768c..af46044fa (18 files, +479/-120) as the focus area, with the wider Windows-port diff as context. The R6 dependency (#2418) was reviewed separately per the request.

Overall: The new work is clean, idiomatic, and well-covered by table-driven tests. The response-file quoting (GNU vs CommandLineToArgvW rules), MSVC import-library resolution, and the explicit toolchain-selection helpers (useSystemClangForTarget, clangDriverTargetForHost, espClangDownload) are all thoughtfully implemented with accurate explanatory comments. No blocking issues found.

A few minor observations are left inline. Highlights:

  • Multi--L search order in resolveMSVCImportLibraries: a name.lib in a later -L dir suppresses rewriting a libname.dll.a in an earlier dir, which can diverge from the linker's own per-directory resolution. Fine for single-dir cases; worth confirming against real MSYS2 layouts.
  • Error context: the llvm-ar archive step returns cmd.Run()'s error bare — wrapping it would ease diagnosing Windows CI failures.
  • Magic-string coupling between espClangDownload and getESPClangPlatform via the literal "x86_64-w64-mingw32".
  • Redundant PATHEXT scan per PATH entry in executableCandidates.

Adjacent (pre-existing, not changed here, mentioned for awareness): extractZip in internal/crosscompile/fetch.go lacks the Zip-Slip path-containment guard that extractTarGz already has, and downloaded toolchains have no checksum verification. Both are outside this PR's scope but live in the same subsystem this port touches.

Comment thread internal/clang/clang.go
Comment thread internal/crosscompile/compile/compile.go
Comment thread internal/crosscompile/crosscompile.go Outdated
Comment thread xtool/env/env.go Outdated
@cpunion

cpunion commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator Author

@fennoai /review

@fennoai

fennoai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

FennoAI is processing your request, please wait a moment...

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: R7-only range b0676768c..af46044fa (18 files, +479/-120)

Scoped to the R7-only diff as requested. Overall this is a clean, well-reasoned change: the NativeToolchain/ResponseFileStyle typed capabilities, the Windows vs GNU response-file quoting split (CommandLineToArgvW backslash-doubling), and the bsdtar-vs-MSYS-tar handling are all correct and well tested (clang_test.go, crosscompile_test.go). One inline nit below; two adjacent-context items worth a decision are noted here.

Adjacent context (not introduced by the changed lines, but touched by this PR's theme):

  • No integrity/checksum verification of the new Windows toolchain download. This diff adds a new third-party executable source espClangWindowsBaseUrl = "https://github.com/espressif/llvm-project/releases/download/esp-19.1.2_20250312" (internal/crosscompile/crosscompile.go). The archive is extracted and its clang++/lld binaries are executed directly, with no pinned SHA-256. HTTPS protects transport but not artifact contents. Consider pinning and verifying a digest for each download URL. (Pre-existing gap for other sources too, but this PR introduces a new source.)

  • Zip-slip guard missing in extractZip (internal/crosscompile/fetch.go). extractTarGz rejects entries escaping dest (strings.HasPrefix(target, filepath.Clean(dest)+separator)), but extractZip joins file.Name to dest with no equivalent check. extractZip itself is outside the changed lines, but it sits beside the extractTarXz refactor in this diff and is reachable for .zip lib downloads. Worth mirroring the tar guard (and a traversal test case) since the extraction paths are being reworked here.

Comment thread xtool/env/env.go Outdated
@fennoai

fennoai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

FennoAI is processing your request, please wait a moment...

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: full PR diff vs main (6fe8babd...af46044f)

This /review had no focus, so this pass covers the full PR diff against main. Note the PR is the stacked R6 (#2418) + R7 change, so its diff vs main is large (~394 files) and includes the R6 runtime/stdlib work that the author states was reviewed separately. I concentrated the four review passes on the substantive non-fixture source (runtime Windows code, internal/build, internal/clang, internal/crosscompile, xtool/env, cl/compile.go) and skipped the mechanical _testgo/_testrt fixture regenerations.

Overall this is high-quality, unusually well-documented work: the Windows runtime shims (SEH fault handling, FLS/TLS lifecycle, WaitOnAddress sema, BCryptGenRandom), the COFF/MSVC toolchain handling, and the response-file quoting split all held up under review, with strong compile-time ABI assertions. Documentation-accuracy found no issues. One inline nit below; a few items already raised in the prior R7-scoped review are summarized here for completeness.

Already noted in the prior R7 review (not re-posting inline):

  • Zip-slip guard missing in extractZip (internal/crosscompile/fetch.go): extractTarGz rejects entries escaping dest, but extractZip does not, though it's reachable via .zip lib downloads (e.g. picolibc). Pre-existing, but worth mirroring the tar guard.
  • No checksum/signature verification of downloaded toolchain archives that are later extracted and executed (fetch.go/crosscompile.go), including the new Windows ESP Clang source. Consider pinning SHA-256 per URL.
  • xtool/env/env.go: inner path loop variable shadows the outer PATH string, and PATHEXT is re-scanned/allocated once per PATH entry despite being invariant.

Comment thread runtime/internal/clite/libuv/config_windows.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant