Compile auto-generated Swift sources (Bundle.module, asset symbols) in Tier 2#131
Merged
Compile auto-generated Swift sources (Bundle.module, asset symbols) in Tier 2#131
Conversation
SPM emits resource_bundle_accessor.swift (defining Bundle.module) under <binPath>/<Target>.build/DerivedSources/ when a target declares .process/.copy resources. SPMBuildSystem.collectSourceFiles only walked Sources/<Target>/, so previews that reference Bundle.module failed to compile with "type 'Bundle' has no member 'module'". Add a pure static helper, collectGeneratedSources(binPath:targetName:), and union its results into BuildContext.sourceFiles after swift build. Shallow glob with no filename whitelist — SPM may rename/add generated files across Swift versions. Example coverage: examples/spm/Sources/ToDo now declares a resource bundle (Localizable.xcstrings) and ToDoView uses Bundle.module, so existing basicMacOSSnapshot test fails at compile time if this fix regresses. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
xcodebuild emits GeneratedAssetSymbols.swift (and GeneratedStringSymbols, GeneratedPlistSymbols, Core Data NSManagedObject subclasses, etc.) into <DERIVED_FILE_DIR>/DerivedSources/. OutputFileMap.json — which XcodeBuildSystem.collectSourceFiles reads — only lists the swift-driver's input files, not these generated ones, so previews referencing Color(.brandPrimary) / Image.foo asset-symbol extensions failed to compile. Add a pure static helper, XcodeBuildSystem.collectGeneratedSources(derivedFileDir:), and union its results into BuildContext.sourceFiles alongside the OutputFileMap sources. Shallow glob with no filename whitelist — Xcode's generator set changes across releases. Examples: xcodeproj and xcworkspace now ship an Assets.xcassets with a BrandPrimary color, explicitly set ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES (the framework-target default isn't reliable across XcodeGen versions), and ToDoView uses Color(.brandPrimary). Existing snapshotXcodeproj / snapshotXcworkspace tests fail at compile time if this fix regresses. xcodegen version: 2.44.1 (pbxproj is gitignored; CI regenerates on demand). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rules_swift's swift_library does not synthesize a Bundle.module accessor the way SPM does, so there is no analogous file for BazelBuildSystem to pick up. Record the decision and the known gaps (swift_proto_library, swift_grpc_library, consumer-macro outputs) where future work would extend this method. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
llbuild's task database (.build/build.db) is shared across triples and can become inconsistent when the same package is built for multiple triples in different processes — typically: $ swift test --filter PreviewsCoreTests # builds example for macOS $ swift test --filter CLIIntegrationTests # also builds for iOS The second invocation hits "command X not registered" errors as llbuild tries to use a task graph node whose registration was overwritten by the previous build. Reproduces deterministically when the two test suites run as separate invocations; ~99 cascading failures. Add SPMBuildRecovery.runSwift(arguments:workingDirectory:) which wraps swift build, parses the offending path out of stderr on failure, removes the affected .build/<triple>/ AND the shared .build/build.db, and retries once. SPMBuildSystem and SetupBuilder both route through it. Verified: PreviewsCoreTests then CLIIntegrationTests as separate invocations now passes all 271 tests (was 99 failures). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extract the cleanup step into cleanStaleArtifacts(tripleDir:) and add two tests: one that verifies both <triple>/ and the sibling build.db are removed (and a peer triple dir is preserved), and one that confirms the helper tolerates missing paths. Closes the only meaningful coverage gap in the recovery flow — the parser was already tested, the runSwift() composition is now trivial. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The recovery's cleanup deletes both .build/<triple>/ and the shared .build/build.db. The parser previously walked up to whatever directory sat under .build/, so a future SPM error mentioning a path under something like .build/workspace-state/ would have caused us to nuke that directory plus the database — well outside the bug's scope. Add looksLikeTriple() and require the resolved directory to match the 3+ hyphen-separated lowercase-token shape (arm64-apple-macosx, arm64-apple-ios-simulator, x86_64-unknown-linux-gnu). Negative test locks in the workspace-state case. Also adds a nit-test verifying SPMBuildSystem.collectGeneratedSources filters by .swift extension. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three fixes around SPM/Xcode build-system integration:
<binPath>/<Target>.build/DerivedSources/*.swiftand append to the compile set. Surfacesresource_bundle_accessor.swiftso previews usingBundle.modulebuild.<DERIVED_FILE_DIR>/DerivedSources/*.swiftand append. SurfacesGeneratedAssetSymbols.swift,GeneratedStringSymbols.swift, etc. so previews usingColor(.brandPrimary)/Image.foobuild.swift buildafter cleaning.build/<triple>/+.build/build.dbwhen llbuild reports"command X not registered"(a known incremental-state bug across cross-process / cross-triple invocations).Bazel is documented-N/A —
rules_swift.swift_librarydoes not synthesize aBundle.moduleequivalent. Comment records known adjacent gaps (swift_proto_library,swift_grpc_library, consumer-macro outputs).The first two are pure static helpers plus a single-line call site in
build(). No change toBuildContextorCompiler— the existingsourceFiles: [URL]?→Compiler.compileCombined(additionalSourceFiles:)pipeline already carries arbitrary URLs.Failing-before repros
Example updates
examples/spm/declaresresources: [.process("Resources")]and shipsLocalizable.xcstrings;ToDoViewreadsBundle.module.localizedString(...).examples/xcodeproj/andexamples/xcworkspace/shipAssets.xcassets/BrandPrimary.colorset, setASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS: YESexplicitly (the library-target default isn't reliable across XcodeGen versions), andToDoViewusesColor(.brandPrimary).xcodegen generate(the existingsnapshotXcodeprojtest already does this).Regression coverage
Existing integration tests now transparently exercise the generated-source paths because the examples they drive use
Bundle.module/Color(.brandPrimary):SnapshotCommandTests.basicMacOSSnapshot(SPM)SnapshotCommandTests.snapshotXcodeproj(Xcode project)SnapshotCommandTests.snapshotXcworkspace(Xcode workspace)New unit tests for the helpers (no
swift build/xcodebuildrequired):BuildSystemTests.collectGeneratedSources_spm_findsResourceAccessor/_emptyWhenMissingBuildSystemTests.collectGeneratedSources_xcode_findsDerivedSwift/_emptyWhenMissingSPMBuildRecoveryTests.parseStaleTripleDirectory*(4 cases)Test plan
swift test --filter 'BuildSystemTests'— 57 tests passswift test --filter 'SPMBuildRecoveryTests'— 4 tests passswift test --filter 'SnapshotCommandTests.basicMacOSSnapshot'passes after fixswift test --filter 'SnapshotCommandTests.snapshotXcodeproj'passesswift test --filter 'SnapshotCommandTests.snapshotXcworkspace'passesswift test --filter PreviewsCoreTests && swift test --filter CLIIntegrationTests— 0 failures (was 99 before SPMBuildRecovery)previewsmcp snapshotagainst both examples produces valid PNGsKnown adjacent issues (not fixed here)
DesignTimeStore.shared.string(...)returningString, which breaksString(localized: "...", bundle: .module)(requiresString.LocalizationValue). The example usesBundle.module.localizedString(forKey:value:table:)instead. Fixing the thunk generator is out of scope for this PR.🤖 Generated with Claude Code