Hive Hive
Sign in

perf(cli): consolidate Swift framework search paths

GitHub issue · Closed

Metadata
Source
tuist/tuist #11555
Updated
Jul 5, 2026
Domains
Cache Generated projects
Details

What changed

Tuist now consolidates Swift framework search paths for targets that depend on many cached or external precompiled frameworks.

The mapper creates a generated per-target search directory under Derived/FrameworkSearchPaths/Swift/<target>, adds symbolic links for uniquely named .framework and .xcframework artifacts, and passes that single directory through OTHER_SWIFT_FLAGS.

It also adds side-effect support for symbolic links and cleans stale generated framework links when the graph changes.

Why

A reproduction showed that large projects can emit hundreds of Swift -F entries when cached frameworks are restored into separate artifact directories. Swift import resolution walks those search paths while resolving imports, so every additional generated framework directory adds repeated filesystem work during clean builds.

Root cause

FrameworkSearchPathsGraphMapper already consolidated the framework paths used by Clang and the linker into response files, but Swift still received every precompiled framework directory inline. That avoided an Xcode 26 issue where the ClangImporter and integrated SwiftDriver mishandle an @file token in Swift flags, but it left Swift with the full generated search-path list.

Approach

This keeps the response-file behavior for Clang and linking unchanged, then gives Swift a separate generated lookup root.

Only artifacts with unique basenames are linked into the generated Swift search directory. Conflicting framework names stay inline so lookup behavior remains deterministic, and unsupported precompiled artifact paths also stay inline.

Impact

Targets with many precompiled frameworks pass far fewer Swift framework search paths, which reduces the filesystem work during import resolution. Smaller targets below the existing consolidation threshold keep the previous FRAMEWORK_SEARCH_PATHS behavior.

Validation

  • mise run cli:lint --fix
  • tuist generate tuist TuistGenerator TuistGeneratorTests ProjectDescription --no-open
  • xcodebuild test -workspace Tuist.xcworkspace -scheme Tuist-Workspace -only-testing TuistGeneratorTests/FrameworkSearchPathsGraphMapperTests -only-testing TuistGeneratorTests/SideEffectDescriptorExecutorTests CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY="" COMPILATION_CACHE_ENABLE_CACHING=NO
Flights

Investigate, reproduce, or fix this item in an isolated repository. Each Flight preserves its outcome and agent session.

New Flights are paused Configure model inference, GitHub, and a sandbox provider to start another Flight. Existing results remain available below.
No Flights yet

Start a Flight and preserve its objective, outcome, and session here.

Comments
T
tuist[bot] Jun 29, 2026

🛠️ Tuist Run Report 🛠️

Tests 🧪
Scheme Status Cache hit rate Tests Skipped Ran Commit
TuistAcceptanceTests 86 % 153 0 153 29d2d9cfb
TuistUnitTests 85 % 3041 5 3036 29d2d9cfb
Flaky Tests ⚠️
  • TuistAcceptanceTests: 1 flaky test (View all)
  • TuistUnitTests: 3 flaky tests (View all)
Test case Module Suite
app_with_plugins() TuistKitAcceptanceTests PluginAcceptanceTests
parseTestStatuses_returnsCorrectStatuses() TuistXCResultServiceTests XCResultServiceTests
parseTestWithCustomLabelXCResult() TuistXCResultServiceTests XCResultServiceTests
parseTestXCResult() TuistXCResultServiceTests XCResultServiceTests
Builds 🔨
Scheme Status Duration Commit
TuistAcceptanceTests 1m 38s 29d2d9cfb
TuistUnitTests 3m 3s 29d2d9cfb