Swift Settings in Package.swift: Compilation Flags Guide
Configure Swift Package targets with swiftSettings for platform conditionals, upcoming features, and compiler flags.
The swiftSettings parameter in Package.swift lets you configure compilation behavior per target—platform-specific code, upcoming Swift features, and compiler flags.
Basic Structure
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// swift-tools-version: 6.0
import PackageDescription
let package = Package(
name: "MyPackage",
targets: [
.target(
name: "MyLibrary",
swiftSettings: [
.define("DEBUG_MODE", .when(configuration: .debug)),
.enableUpcomingFeature("StrictConcurrency")
]
)
]
)
Platform Conditionals
Use .define() with .when(platforms:) to create compile-time flags:
1
2
3
4
5
6
7
8
9
.target(
name: "CrossPlatformLib",
swiftSettings: [
.define("IOS", .when(platforms: [.iOS])),
.define("MACOS", .when(platforms: [.macOS])),
.define("LINUX", .when(platforms: [.linux])),
.define("WINDOWS", .when(platforms: [.windows]))
]
)
Then use in Swift code:
1
2
3
4
5
6
7
8
9
10
11
func platformName() -> String {
#if IOS
return "iOS"
#elseif MACOS
return "macOS"
#elseif LINUX
return "Linux"
#else
return "Unknown"
#endif
}
Configuration-Based Flags
Define flags that only apply in debug or release builds:
1
2
3
4
swiftSettings: [
.define("ENABLE_LOGGING", .when(configuration: .debug)),
.define("ENABLE_ANALYTICS", .when(configuration: .release))
]
Usage:
1
2
3
4
5
func log(_ message: String) {
#if ENABLE_LOGGING
print("[DEBUG] \(message)")
#endif
}
Upcoming Features
Enable Swift evolution features before they become default:
1
2
3
4
5
6
swiftSettings: [
.enableUpcomingFeature("StrictConcurrency"),
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("BareSlashRegexLiterals"),
.enableUpcomingFeature("InferSendableFromCaptures")
]
Check available features with:
1
swift build --help | grep -i upcoming
Memory Safety
Enforce strict memory safety checking:
1
2
3
swiftSettings: [
.strictMemorySafety()
]
This enables additional compile-time checks for memory safety violations.
Unsafe Flags
Pass raw compiler flags (use sparingly):
1
2
3
swiftSettings: [
.unsafeFlags(["-Xfrontend", "-warn-long-expression-type-checking=100"])
]
Warning: Targets using .unsafeFlags() cannot be used as dependencies by other packages.
Complete Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// swift-tools-version: 6.0
import PackageDescription
let applePlatforms: [Platform] = [.iOS, .macOS, .tvOS, .watchOS, .visionOS]
let package = Package(
name: "CrossPlatformKit",
platforms: [.iOS(.v18), .macOS(.v15)],
products: [
.library(name: "CrossPlatformKit", targets: ["CrossPlatformKit"])
],
targets: [
.target(
name: "CrossPlatformKit",
swiftSettings: [
// Platform detection
.define("DARWIN", .when(platforms: applePlatforms)),
.define("IOS", .when(platforms: [.iOS])),
.define("LINUX", .when(platforms: [.linux])),
// Configuration flags
.define("DEBUG_MODE", .when(configuration: .debug)),
// Swift 6 preparation
.enableUpcomingFeature("StrictConcurrency")
]
)
]
)
When to Use Each Setting
| Setting | Use Case |
|---|---|
.define() | Platform-specific code paths, debug toggles |
.enableUpcomingFeature() | Adopt Swift evolution features early |
.strictMemorySafety() | Enforce memory safety in Swift 6+ |
.unsafeFlags() | Debugging, diagnostics (not for distributed packages) |
Important Notes
- Platform conditionals compile out unused code paths
- Upcoming features help migrate to new Swift versions incrementally
.unsafeFlags()breaks package distribution—use only for local development- Combine
.when(platforms:)and.when(configuration:)for granular control
☕ Support My Work
If you found this post helpful and want to support more content like this, you can buy me a coffee!
Your support helps me continue creating useful articles and tips for fellow developers. Thank you! 🙏