Hive Hive
Sign in

feat(cli): support SwiftPM prebuilt libraries

GitHub issue · Closed

Metadata
Source
tuist/tuist #11112
Updated
Jun 24, 2026
Domains
Generated projects
Details

Resolves N/A

Adds support for SwiftPM prebuilts entries in workspace-state.json, which SwiftPM now uses for precompiled SwiftSyntax macro support libraries. Macro and plugin dependency paths can now consume SwiftPM’s prebuilt MacroSupport library, while regular runtime dependencies on SwiftSyntax continue to use source or cached framework targets.

  • Decode SwiftPM prebuilt metadata and forward it into external package mapping.
  • Replace eligible macro/plugin product dependencies with the prebuilt include, library search, and linker settings SwiftPM expects.
  • Keep non-host dependencies on source targets so runtime SwiftSyntax products are not accidentally substituted by macro-only prebuilts.
  • Add focused mapper and graph-loader tests for prebuilt forwarding, macro substitution, and runtime dependency preservation.

How to test locally

  • swiftformat cli/Sources/TuistLoader/SwiftPackageManager/PackageInfoMapper.swift cli/Sources/TuistLoader/Loaders/SwiftPackageManagerGraphLoader.swift cli/Sources/TuistLoader/Models/SwiftPackageManagerWorkspaceState.swift cli/Sources/TuistLoader/Models/SwiftPackageManagerPrebuilt.swift cli/Tests/TuistLoaderTests/Loaders/SwiftPackageManagerGraphLoaderTests.swift cli/Tests/TuistLoaderTests/SwiftPackageManager/PackageInfoMapperTests.swift
  • xcodebuild test -workspace Tuist.xcworkspace -scheme TuistUnitTests -only-testing TuistLoaderTests/PackageInfoMapperTests/map_whenMacroTargetDependsOnPrebuiltProduct_usesPrebuiltSettings -only-testing TuistLoaderTests/PackageInfoMapperTests/map_whenRegularTargetDependsOnPrebuiltProduct_keepsSourceDependency -only-testing TuistLoaderTests/SwiftPackageManagerGraphLoaderTests/load_whenWorkspaceStateContainsPrebuilts_passesPackagePrebuiltsToMapper CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=""
  • TUIST_EE=1 .build/arm64-apple-macosx/debug/tuist generate tuist ProjectDescription --no-open
  • TUIST_EE=1 xcodebuild build -workspace Tuist.xcworkspace -scheme tuist -configuration Debug SYMROOT=/tmp/tuist-ee-products CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=""
  • In ~/Downloads/precompiled/MacroApp: /tmp/tuist-ee-products/Debug/tuist install, /tmp/tuist-ee-products/Debug/tuist cache warm --cache-profile all-possible, /tmp/tuist-ee-products/Debug/tuist generate --cache-profile all-possible --no-open, and xcodebuild build -workspace MacroApp.xcworkspace -scheme App -destination 'generic/platform=iOS Simulator' CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=""
  • In ~/Downloads/precompiled/RuntimeSwiftSyntax: /tmp/tuist-ee-products/Debug/tuist install, /tmp/tuist-ee-products/Debug/tuist cache warm --cache-profile all-possible, /tmp/tuist-ee-products/Debug/tuist generate --cache-profile only-external --no-open, and xcodebuild build -workspace RuntimeSwiftSyntax.xcworkspace -scheme RuntimeSwiftSyntax -destination 'generic/platform=macOS' CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=""
  • git diff --check
Comments
T
tuist[bot] Jun 5, 2026

🛠️ Tuist Run Report 🛠️

Previews 📦
App Commit Open on device
Tuist 5a6d2dccd
Tests 🧪
Scheme Status Cache hit rate Tests Skipped Ran Commit
TuistAcceptanceTests 0 % 0 0 0 5a6d2dccd
TuistUnitTests 0 % 1825 28 1797 3bf90c229
Builds 🔨
Scheme Status Duration Commit
TuistAcceptanceTests 6m 0.6s 5a6d2dccd
TuistApp 8m 19s 5a6d2dccd
TuistUnitTests 6m 35s 3bf90c229
Bundles 🧰
Bundle Commit Install size Download size
Tuist 5a6d2dccd 19.5 MB 14.7 MBΔ +2 B (+0.00%)
F
fortmarek Jun 5, 2026

I found two behavioral issues in the mapper path:

  1. PackageInfoMapper.swift: prebuiltEligibleTargets marks plugin targets as prebuilt-eligible (case .macro, .plugin), but map(target:) still filters plugin targets out before dependency mapping (case .regular, .system, .macro, .test is the only pass-through set). As a result the advertised plugin path never gets far enough to apply the prebuilt settings, while plugin targets can still influence the host-only eligibility heuristic. I think we should either map plugin targets here or remove .plugin from this new prebuilt path and coverage claim.

  2. PackageInfoMapper.swift: prebuiltDependency calls ProjectDescription.PlatformCondition.from(condition) directly, while the normal mapDependency path catches conversion failures and skips the dependency. A prebuilt product dependency with an unsupported or config-only condition would now fail generation instead of being ignored. I think this should mirror the existing catch-and-return-nil behavior.

One broader testing note: I think this should also be covered end-to-end with an acceptance test. We originally disabled the macro acceptance tests because building SwiftSyntax/macros was too heavy, but this feature should make that scenario fast because the macro support library is expected to come from the SwiftPM prebuilt. An acceptance fixture that runs install/generate/build for a macro target with SwiftPM prebuilts would protect the real workspace-state.json decoding + graph loading + generated Xcode build settings path, which the current focused unit tests do not fully exercise.

P
pepicrft Jun 5, 2026

Thanks Marek. I addressed these in d428823417:

  • Plugin targets no longer seed the prebuilt eligibility closure, since they are still filtered out before graph mapping.
  • Prebuilt product dependencies now mirror the regular dependency path and skip unsupported or config-only conditions instead of failing generation.
  • Added focused mapper coverage for both edge cases.
  • Added an end-to-end acceptance fixture that runs install, generate, and build for a Project.swift app depending on a Package.swift macro package backed by SwiftSyntax prebuilts.

I also verified the focused unit tests and the new acceptance test locally. The current macOS CI failures do not show a test assertion or compile error. Both jobs were terminated mid-Xcode build while the step was still in progress, so I reran the failed jobs to validate with warmed caches.

TA
tuist-atlas[bot] Jun 9, 2026

The support for SwiftPM prebuilt libraries is now available in 4.197.0. Update to this version to use it.