Swift Package Compiler Flags in Tuist#
Tuist maps Swift Package Manager (SPM) packages into Xcode projects via PackageInfoMapper. A key part of that mapping is populating OTHER_SWIFT_FLAGS (and companion build settings) with the right compiler flags so each generated target behaves identically to how SwiftPM would build it.
Two source files drive this:
| File | Role |
|---|---|
PackageInfoMapper.swift | Orchestrates per-target and per-project settings, injects -package-name and -module-alias |
SettingsMapper.swift | Converts raw PackageInfo.Target.TargetBuildSettingDescription.Setting values into XcodeGraph.SettingsDictionary entries |
-package-name (Swift 5.9+)#
The package access level modifier introduced in Swift 5.9 requires the compiler to know what package a module belongs to. Tuist injects this at the project level in PackageInfo.projectSettings().
When the package's tools-version is >= 5.9.0, Tuist appends ["$(inherited)", "-package-name", <name>] to OTHER_SWIFT_FLAGS . The flag value is the package name, quoted if it contains spaces. The implementation merges cleanly with any pre-existing value in the setting β handling .array, .string, and .none variants β so that base settings supplied by the user are never overwritten .
Because this is set at project scope (not target scope), the flag is automatically inherited by every target in the generated .xcodeproj for that package.
-module-alias#
SPM allows a dependency to be imported under a different name via moduleAliases. Tuist tracks these during dependency resolution and surfaces them in OTHER_SWIFT_FLAGS for each target that uses an aliased dependency.
Collection phase β inside mapDependency, when a dependency has an alias entry, the mapping originalName β aliasedName is stored in dependencyModuleAliases . The target dependency itself is registered under the aliased name.
Application phase β in Settings.from(), the collected aliases are flattened into pairs ["-module-alias", "OriginalName=AliasedName", ...] and appended to OTHER_SWIFT_FLAGS. Like the -package-name logic, it handles both .array and .string forms of any pre-existing value .
This mirrors what SwiftPM itself passes to the compiler when a package uses module aliasing.
SettingsMapper: Per-Target Swift Flags#
SettingsMapper handles the build settings declared inside a target's manifest (.target(settings:)). Its map() function accumulates flags into typed arrays, then writes them all at once:
| Manifest setting | Emitted flag | Xcode key |
|---|---|---|
.unsafeFlags (swift) | raw values passed through | OTHER_SWIFT_FLAGS |
.enableUpcomingFeature | -enable-upcoming-feature "<name>" | OTHER_SWIFT_FLAGS |
.enableExperimentalFeature | -enable-experimental-feature "<name>" | OTHER_SWIFT_FLAGS |
.strictMemorySafety | -strict-memory-safety (+ optional -Werror=StrictMemorySafety) | OTHER_SWIFT_FLAGS |
.swiftLanguageMode | -swift-version <mode> + SWIFT_VERSION setting | OTHER_SWIFT_FLAGS + SWIFT_VERSION |
.treatAllWarnings (swift) | -warnings-as-errors or -no-warnings-as-errors | OTHER_SWIFT_FLAGS |
All collected swiftFlags are written to OTHER_SWIFT_FLAGS as ["$(inherited)"] + swiftFlags , ensuring parent build settings are always preserved.
SettingsMapper is instantiated inside Settings.from() in PackageInfoMapper , and mapSettings() is called before -module-alias flags are appended , so the final OTHER_SWIFT_FLAGS value is the union of all sources.
Prebuilt Dependencies and Include Paths#
For targets that depend on prebuilt libraries (e.g., cached XCFrameworks), Tuist also appends -I <path> include search path pairs to OTHER_SWIFT_FLAGS so the compiler can locate the prebuilt module's headers . This happens after SettingsMapper output and -module-alias flags have been merged.
Layering Order#
OTHER_SWIFT_FLAGS for each target is seeded with ["$(inherited)"] before any mapper runs . Flags are then appended in this order:
- SettingsMapper output β manifest-declared settings merged on top .
-module-aliaspairs β one pair per aliased dependency .- Prebuilt
-Ipaths β include search paths for cached XCFrameworks .
The project-level OTHER_SWIFT_FLAGS (carrying -package-name) is set separately in projectSettings() and is inherited by every target in that project via Xcode's standard build setting inheritance.