builder: add -trimpath support - #5711
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
CGo headers outside the package directory can still expose local paths and prevent reproducible cache keys.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
What changed in this PR
Adds -trimpath support to remove local paths and improve binary reproducibility.
Changes:
- Adds and propagates the
-trimpathoption. - Rewrites Go, CGo, library, and embedded-file paths.
- Adds path-removal and reproducibility tests.
| File | Description |
|---|---|
main.go |
Adds the CLI flag. |
main_test.go |
Tests the flag and output reproducibility. |
compileopts/options.go |
Stores the option. |
compileopts/config.go |
Configures path mapping and cache isolation. |
compiler/compiler.go |
Records mapped debug paths. |
loader/loader.go |
Maps package paths and flags. |
loader/loader_test.go |
Tests module path mapping. |
cgo/cgo.go |
Maps CGo source locations. |
cgo/cgo_test.go |
Updates the CGo call signature. |
builder/build.go |
Applies mapping during builds. |
builder/library.go |
Applies mapping to C libraries. |
testdata/trimpath/main.go |
Adds the integration test program. |
testdata/trimpath/main.c |
Adds test C code. |
testdata/trimpath/go.mod |
Defines the test module. |
testdata/trimpath/dependency/go.mod |
Defines the test dependency. |
testdata/trimpath/dependency/dependency.go |
Adds dependency code. |
testdata/trimpath/data.txt |
Adds embedded test data. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
092c129 to
2659e1c
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Darwin cross-builds can fail on Windows because the linker preparation requires symbolic-link privileges.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (1)
Resolved since last review (1)
2659e1c to
c2b7eda
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Module-less GOPATH packages can still retain absolute paths for shared C headers.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (1)
Resolved since last review (1)
c2b7eda to
6ee2500
Compare
|
I know that this feature is wanted, for example #5275 Any update here? |
|
Just dealing with copilot back and forth, will undraft when I feel like it's not missing any weird cases. |
eccdbe5 to
2495957
Compare
|
@jakebailey please rebase and resolve merge conflicts. Thank you. |
7080803 to
2f14a87
Compare
|
Thanks for all the work on this @jakebailey. I ran the tests on my local machine and took a good look. The following is edited from an automated review:
What do you think of these? |
|
Generated CGo globals can share a source position. Break these ties by name so independent compilations produce the same bitcode and ThinLTO symbol names instead of depending on Go map iteration order.
Local source and cache paths make binaries depend on the build directory and expose the builder filesystem layout. Trim these paths from debug information and C __FILE__ strings, including with -no-debug. Leave the compiled-in runtime.GOROOT empty in trimmed builds, matching Go. Match Go's C compilation directories in both modes so trimpath does not change header lookup. Relative C flags now resolve from the source directory instead of the command's working directory. Keep source paths usable for debugger substitution and package-size reports. Compare independent builds with separate caches so cache reuse does not hide nondeterministic output. Fixes 5275
LLD 15 records ThinLTO cache paths and object timestamps in Mach-O outputs. These make trimmed binaries depend on cache location and build time even when their source paths have been removed. LLD 16 changed cached-object handling in https://reviews.llvm.org/D131624. Disable ThinLTO caching only for trimmed Darwin builds on LLVM 15, and suppress object timestamps. Other compilation caches remain enabled. Exercise Darwin trimpath builds in the oldest-toolchain compatibility job.
Some Clang builds record compiler arguments in debug information by default. Those arguments contain source, cache, and temporary paths that prefix maps do not rewrite. Even when the final binary omits that debug information, the paths affect ThinLTO symbol hashes. Disable command-line recording for trimmed C sources and libraries. The LLVM 18.1.8 Darwin regression reproduces this with independent builds.
Compiler-provided headers can live outside the TinyGo source tree when using a system LLVM installation. Their absolute paths remain in DWARF, as seen with __stddef_size_t.h in WASI test binaries on LLVM 18 and 19. Use the known Clang resource directory for trimmed builds so its headers can be recorded under a stable clang path. Apply this to both package compilation and cached libraries.
Trimmed path lookups repeatedly resolve every package and module root. This repeats filesystem work for synthetic GOROOT paths and visits the same module once per package. Build immutable directory mappings after loading the package graph and deduplicate shared roots. Keep package mappings ahead of module mappings, with the same longest-directory and lexical tie-breaking rules. Add lookup benchmarks for 10, 100, and 1000 packages and regression coverage for mapping precedence and path boundaries.
2f14a87 to
6bf41a8
Compare
deadprogram
left a comment
There was a problem hiding this comment.
Thank you very much for everything on this @jakebailey now merging!
|
@jakebailey Was this PR built with AI assistance? |
|
To some extent, yes |
|
@jakebailey Which model did you use? |

Fixes #5275
With
-no-debug, this doesn't really matter, but otherwise it does make binaries smaller and more reproducible.