build: split package execution stages - #2176
Conversation
There was a problem hiding this comment.
Review summary
This is a well-structured refactor that cleanly separates the package build pipeline into preflight/execute/finalize stages and defers SSA building into a bounded worker pool, in preparation for parallel compilation. The concurrency boundary is drawn correctly: ssa.Package.Build() is documented as thread-safe and is the only work parallelized, while the mutating fixSSAOrder pass and the LLVM backend remain serial. effectiveDependencies correctly folds alt-package imports into fingerprinting, and the -p flag path validates and applies atomically. Good test coverage on the new helpers.
Two findings are noted inline. Security and documentation-accuracy passes found no actionable issues.
Minor (no inline): packageBuildResult fields spec, cacheHit, and archiveFile (internal/build/package_build.go) are populated by packageBuildResultFor but read only in tests; production code consumes only needRuntime/needPyInit. The comments frame these as scaffolding for a future scheduler PR, so this is acceptable, but reviewers should confirm the forward-looking fields are intended to land ahead of their consumer.
| "gcflags", | ||
| "gccgoflags", | ||
| "ldflags", | ||
| "p", |
There was a problem hiding this comment.
Adding p to argumentListFlagNames conflates two different semantics. This list is needed by normalizeBuildFlags/argumentListBuildFlag (normalize.go) so that a space-separated -p 4 normalizes to -p=4 — that part is correct. But the same list also drives wholeLineValueFlag (flagfile.go:65-81), which treats the entire rest of a flags-file line as one unsplit value. That behavior is intended for flags whose value is an argument list (gcflags, ldflags, toolexec), not for a scalar integer flag.
Consequence: in a flags file, a line like -p=4 -tags=foo is captured as the single flag -p=4 -tags=foo (the -tags=foo is swallowed into -p's value) instead of being split into two flags.
Consider using a separate set for scalar flags that accept a detached value vs. flags whose value is an argument list, or excluding p from the whole-line path. At minimum, add a test covering -p combined with another flag on one flags-file line.
| unique := make([]ssaBuildEntry, 0, len(entries)) | ||
| seen := make(map[*ssa.Package]bool, len(entries)) | ||
| for _, entry := range entries { | ||
| if entry.pkg == nil || seen[entry.pkg] { |
There was a problem hiding this comment.
The dedup keeps the first-seen entry per *ssa.Package and drops later duplicates. Entries are concatenated as altEntries (fixOrder:false), then pkgEntries (fixOrder:true), then depEntries (see the append(append(altEntries, pkgEntries...), depEntries...) call). If the same *ssa.Package ever appeared in both an alt entry and a normal entry, the fixOrder:false alt entry would win and fixSSAOrder would be silently skipped for that package.
Today alt packages are distinct *ssa.Package instances (they carry altPkgPathPrefix and registerSSAPkgs skips those paths), so no real collision occurs — hence low severity. As cheap future-proofing, OR the fixOrder flag when merging a duplicate rather than first-wins, so a missing ordering fix can't surface as a hard-to-diagnose failure after a future change.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
6c9c543 to
475f24b
Compare
475f24b to
6b7aa0b
Compare
6b7aa0b to
7126afd
Compare
|
This PR has been absorbed into #2175 during the parallel-build stack consolidation. The retained PR now contains the explicit build units and preflight/execute/finalize stage split. |
Summary
Validation
GOCACHE=/private/tmp/llgo-pr2-gocache go test ./internal/build ./internal/goflags ./cmd/internal/flags -count=1Dependency
This PR includes and depends on #2174 and #2175. Merge/rebase it after those PRs; it will then contain only this stage split.