Skip to content

Commit c04d067

Browse files
committed
enable clang modules only on darwin platforms
- the native builder only enables clang modules on Darwin, so we will need to do the same with swift-build. - update settings handling to use new subscript with platform specifier instead of deprecated platformSpecificSettings property.
1 parent 7046c68 commit c04d067

File tree

6 files changed

+156
-181
lines changed

6 files changed

+156
-181
lines changed

Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift

Lines changed: 132 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -524,14 +524,93 @@ extension PackageGraph.ResolvedModule {
524524
}
525525

526526
struct AllBuildSettings {
527-
typealias BuildSettingsByPlatform =
528-
[ProjectModel.BuildSettings.Platform?: [BuildSettings.Declaration: [String]]]
527+
typealias SingleValueSettingsByPlatform =
528+
[ProjectModel.BuildSettings.Platform?: [ProjectModel.BuildSettings.SingleValueSetting: String]]
529+
typealias MultipleValueSettingsByPlatform =
530+
[ProjectModel.BuildSettings.Platform?: [ProjectModel.BuildSettings.MultipleValueSetting: [String]]]
529531

530-
/// Target-specific build settings declared in the manifest and that apply to the target itself.
531-
var targetSettings: [BuildConfiguration: BuildSettingsByPlatform] = [:]
532+
/// Target-specific single-value build settings declared in the manifest and that apply to the target itself.
533+
var targetSingleValueSettings: [BuildConfiguration: SingleValueSettingsByPlatform] = [:]
534+
535+
/// Target-specific multiple-value build settings declared in the manifest and that apply to the target itself.
536+
var targetMultipleValueSettings: [BuildConfiguration: MultipleValueSettingsByPlatform] = [:]
532537

533-
/// Target-specific build settings that should be imparted to client targets (packages and projects).
534-
var impartedSettings: BuildSettingsByPlatform = [:]
538+
/// Target-specific single-value build settings that should be imparted to client targets (packages and projects).
539+
var impartedSingleValueSettings: SingleValueSettingsByPlatform = [:]
540+
541+
/// Target-specific multiple-value build settings that should be imparted to client targets (packages and projects).
542+
var impartedMultipleValueSettings: MultipleValueSettingsByPlatform = [:]
543+
544+
// MARK: - Convenience Methods
545+
546+
/// Apply all settings to a ProjectModel.BuildSettings instance
547+
func apply(to buildSettings: inout ProjectModel.BuildSettings, for configuration: BuildConfiguration) {
548+
// Apply single value settings for all platforms
549+
if let singleValuesByPlatform = targetSingleValueSettings[configuration] {
550+
for (platform, singleValues) in singleValuesByPlatform {
551+
for (setting, value) in singleValues {
552+
if let platform = platform {
553+
buildSettings[setting, platform] = value
554+
} else {
555+
buildSettings[setting] = value
556+
}
557+
}
558+
}
559+
}
560+
561+
// Apply multiple value settings for all platforms
562+
if let multipleValuesByPlatform = targetMultipleValueSettings[configuration] {
563+
// First, collect all multiple-value settings that are being used
564+
var usedMultipleValueSettings = Set<ProjectModel.BuildSettings.MultipleValueSetting>()
565+
for (_, multipleValues) in multipleValuesByPlatform {
566+
for (setting, _) in multipleValues {
567+
usedMultipleValueSettings.insert(setting)
568+
}
569+
}
570+
571+
// Now apply the platform-specific values
572+
for (platform, multipleValues) in multipleValuesByPlatform {
573+
for (setting, values) in multipleValues {
574+
if let platform = platform {
575+
// Get existing values (should now be initialized with inherited)
576+
let existingValues = buildSettings[setting, platform] ?? ["$(inherited)"]
577+
buildSettings[setting, platform] = existingValues + values
578+
} else {
579+
// Append to existing values instead of overwriting
580+
let existingValues = buildSettings[setting] ?? ["$(inherited)"]
581+
buildSettings[setting] = existingValues + values
582+
}
583+
}
584+
}
585+
}
586+
}
587+
588+
/// Apply imparted settings to a ProjectModel.BuildSettings instance
589+
func applyImparted(to buildSettings: inout ProjectModel.BuildSettings) {
590+
// Apply imparted single value settings for all platforms
591+
for (platform, singleValues) in impartedSingleValueSettings {
592+
for (setting, value) in singleValues {
593+
if let platform = platform {
594+
buildSettings[setting, platform] = value
595+
} else {
596+
buildSettings[setting] = value
597+
}
598+
}
599+
}
600+
601+
// Apply imparted multiple value settings for all platforms
602+
for (platform, multipleValues) in impartedMultipleValueSettings {
603+
for (setting, values) in multipleValues {
604+
if let platform = platform {
605+
let existingValues = buildSettings[setting, platform] ?? ["$(inherited)"]
606+
buildSettings[setting, platform] = existingValues + values
607+
} else {
608+
let existingValues = buildSettings[setting] ?? ["$(inherited)"]
609+
buildSettings[setting] = existingValues + values
610+
}
611+
}
612+
}
613+
}
535614
}
536615

537616
/// Target-specific build settings declared in the manifest and that apply to the target itself.
@@ -546,20 +625,31 @@ extension PackageGraph.ResolvedModule {
546625
for settingAssignment in settingsAssigments {
547626
// Create a build setting value; in some cases there
548627
// isn't a direct mapping to Swift Build build settings.
549-
let pifDeclaration: BuildSettings.Declaration
550628
let values: [String]
629+
let singleValueSetting: ProjectModel.BuildSettings.SingleValueSetting?
630+
let multipleValueSetting: ProjectModel.BuildSettings.MultipleValueSetting?
631+
551632
switch declaration {
552633
case .LINK_FRAMEWORKS:
553-
pifDeclaration = .OTHER_LDFLAGS
634+
singleValueSetting = nil
635+
multipleValueSetting = .OTHER_LDFLAGS
554636
values = settingAssignment.values.flatMap { ["-framework", $0] }
555637
case .LINK_LIBRARIES:
556-
pifDeclaration = .OTHER_LDFLAGS
638+
singleValueSetting = nil
639+
multipleValueSetting = .OTHER_LDFLAGS
557640
values = settingAssignment.values.map { "-l\($0)" }
558641
case .HEADER_SEARCH_PATHS:
559-
pifDeclaration = .HEADER_SEARCH_PATHS
642+
singleValueSetting = nil
643+
multipleValueSetting = .HEADER_SEARCH_PATHS
560644
values = settingAssignment.values.map { self.sourceDirAbsolutePath.pathString + "/" + $0 }
561645
default:
562-
pifDeclaration = ProjectModel.BuildSettings.Declaration(from: declaration)
646+
if declaration.allowsMultipleValues {
647+
singleValueSetting = nil
648+
multipleValueSetting = ProjectModel.BuildSettings.MultipleValueSetting(from: declaration)
649+
} else {
650+
singleValueSetting = ProjectModel.BuildSettings.SingleValueSetting(from: declaration)
651+
multipleValueSetting = nil
652+
}
563653
values = settingAssignment.values
564654
}
565655

@@ -578,26 +668,19 @@ extension PackageGraph.ResolvedModule {
578668
pifPlatform = nil
579669
}
580670

581-
if pifDeclaration == .OTHER_LDFLAGS {
582-
var settingsByDeclaration: [ProjectModel.BuildSettings.Declaration: [String]]
583-
584-
settingsByDeclaration = allSettings.impartedSettings[pifPlatform] ?? [:]
585-
settingsByDeclaration[pifDeclaration, default: []].append(contentsOf: values)
586-
587-
allSettings.impartedSettings[pifPlatform] = settingsByDeclaration
671+
// Handle imparted settings for OTHER_LDFLAGS (always multiple values)
672+
if let multipleValueSetting = multipleValueSetting, multipleValueSetting == .OTHER_LDFLAGS {
673+
allSettings.impartedMultipleValueSettings[pifPlatform, default: [:]][multipleValueSetting, default: []].append(contentsOf: values)
588674
}
589675

590676
for configuration in configurations {
591-
var settingsByDeclaration: [ProjectModel.BuildSettings.Declaration: [String]]
592-
settingsByDeclaration = allSettings.targetSettings[configuration]?[pifPlatform] ?? [:]
593-
594-
if declaration.allowsMultipleValues {
595-
settingsByDeclaration[pifDeclaration, default: []].append(contentsOf: values)
596-
} else {
597-
settingsByDeclaration[pifDeclaration] = values.only.flatMap { [$0] } ?? []
677+
if let multipleValueSetting = multipleValueSetting {
678+
// Handle multiple value settings
679+
allSettings.targetMultipleValueSettings[configuration, default: [:]][pifPlatform, default: [:]][multipleValueSetting, default: []].append(contentsOf: values)
680+
} else if let singleValueSetting = singleValueSetting, let singleValue = values.only {
681+
// Handle single value settings
682+
allSettings.targetSingleValueSettings[configuration, default: [:]][pifPlatform, default: [:]][singleValueSetting] = singleValue
598683
}
599-
600-
allSettings.targetSettings[configuration, default: [:]][pifPlatform] = settingsByDeclaration
601684
}
602685
}
603686
}
@@ -911,88 +994,8 @@ extension ProjectModel.BuildSettings {
911994
/// Note that this restricts the settings that can be set by this function to those that can have platform-specific
912995
/// values, i.e. those in `ProjectModel.BuildSettings.Declaration`. If a platform is specified,
913996
/// it must be one of the known platforms in `ProjectModel.BuildSettings.Platform`.
914-
mutating func append(values: [String], to setting: Declaration, platform: Platform? = nil) {
915-
// This dichotomy is quite unfortunate but that's currently the underlying model in ProjectModel.BuildSettings.
916-
if let platform {
917-
switch setting {
918-
case .FRAMEWORK_SEARCH_PATHS,
919-
.GCC_PREPROCESSOR_DEFINITIONS,
920-
.HEADER_SEARCH_PATHS,
921-
.OTHER_CFLAGS,
922-
.OTHER_CPLUSPLUSFLAGS,
923-
.OTHER_LDFLAGS,
924-
.OTHER_SWIFT_FLAGS,
925-
.SWIFT_ACTIVE_COMPILATION_CONDITIONS:
926-
// Appending implies the setting is resilient to having ["$(inherited)"]
927-
self.platformSpecificSettings[platform]![setting]!.append(contentsOf: values)
928-
929-
case .SWIFT_VERSION, .DYLIB_INSTALL_NAME_BASE:
930-
self.platformSpecificSettings[platform]![setting] = values // We are not resilient to $(inherited).
931-
932-
case .ARCHS, .IPHONEOS_DEPLOYMENT_TARGET, .SPECIALIZATION_SDK_OPTIONS:
933-
fatalError("Unexpected BuildSettings.Declaration: \(setting)")
934-
// Allow staging in new cases
935-
default:
936-
fatalError("Unhandled enum case in BuildSettings.Declaration. Will generate a warning until we have SE-0487")
937-
}
938-
} else {
939-
switch setting {
940-
case .FRAMEWORK_SEARCH_PATHS,
941-
.GCC_PREPROCESSOR_DEFINITIONS,
942-
.HEADER_SEARCH_PATHS,
943-
.OTHER_CFLAGS,
944-
.OTHER_CPLUSPLUSFLAGS,
945-
.OTHER_LDFLAGS,
946-
.OTHER_SWIFT_FLAGS,
947-
.SWIFT_ACTIVE_COMPILATION_CONDITIONS:
948-
let multipleSetting = MultipleValueSetting(from: setting)!
949-
self[multipleSetting, default: ["$(inherited)"]].append(contentsOf: values)
950-
951-
case .SWIFT_VERSION:
952-
self[.SWIFT_VERSION] = values.only.unwrap(orAssert: "Invalid values for 'SWIFT_VERSION': \(values)")
953-
954-
case .DYLIB_INSTALL_NAME_BASE:
955-
self[.DYLIB_INSTALL_NAME_BASE] = values.only.unwrap(orAssert: "Invalid values for 'DYLIB_INSTALL_NAME_BASE': \(values)")
956-
957-
case .ARCHS, .IPHONEOS_DEPLOYMENT_TARGET, .SPECIALIZATION_SDK_OPTIONS:
958-
fatalError("Unexpected BuildSettings.Declaration: \(setting)")
959-
// Allow staging in new cases
960-
default:
961-
fatalError("Unhandled enum case in BuildSettings.Declaration. Will generate a warning until we have SE-0487")
962-
}
963-
}
964-
}
965997
}
966998

967-
extension ProjectModel.BuildSettings.MultipleValueSetting {
968-
init?(from declaration: ProjectModel.BuildSettings.Declaration) {
969-
switch declaration {
970-
case .GCC_PREPROCESSOR_DEFINITIONS:
971-
self = .GCC_PREPROCESSOR_DEFINITIONS
972-
case .FRAMEWORK_SEARCH_PATHS:
973-
self = .FRAMEWORK_SEARCH_PATHS
974-
case .HEADER_SEARCH_PATHS:
975-
self = .HEADER_SEARCH_PATHS
976-
case .OTHER_CFLAGS:
977-
self = .OTHER_CFLAGS
978-
case .OTHER_CPLUSPLUSFLAGS:
979-
self = .OTHER_CPLUSPLUSFLAGS
980-
case .OTHER_LDFLAGS:
981-
self = .OTHER_LDFLAGS
982-
case .OTHER_SWIFT_FLAGS:
983-
self = .OTHER_SWIFT_FLAGS
984-
case .SPECIALIZATION_SDK_OPTIONS:
985-
self = .SPECIALIZATION_SDK_OPTIONS
986-
case .SWIFT_ACTIVE_COMPILATION_CONDITIONS:
987-
self = .SWIFT_ACTIVE_COMPILATION_CONDITIONS
988-
case .ARCHS, .IPHONEOS_DEPLOYMENT_TARGET, .SWIFT_VERSION, .DYLIB_INSTALL_NAME_BASE:
989-
return nil
990-
// Allow staging in new cases
991-
default:
992-
fatalError("Unhandled enum case in BuildSettings.Declaration. Will generate a warning until we have SE-0487")
993-
}
994-
}
995-
}
996999

9971000
extension ProjectModel.BuildSettings.Platform {
9981001
enum Error: Swift.Error {
@@ -1034,7 +1037,6 @@ extension ProjectModel.BuildSettings {
10341037
self[.PRODUCT_NAME] = productName
10351038
self[.PRODUCT_MODULE_NAME] = productName
10361039
self[.PRODUCT_BUNDLE_IDENTIFIER] = "\(packageIdentity).\(productName)".spm_mangledToBundleIdentifier()
1037-
self[.CLANG_ENABLE_MODULES] = "YES"
10381040
self[.SWIFT_PACKAGE_NAME] = packageName ?? nil
10391041

10401042
if !createDylibForDynamicProducts {
@@ -1061,32 +1063,36 @@ extension ProjectModel.BuildSettings {
10611063
}
10621064
}
10631065

1064-
extension ProjectModel.BuildSettings.Declaration {
1065-
init(from declaration: PackageModel.BuildSettings.Declaration) {
1066-
self = switch declaration {
1067-
// Swift.
1066+
extension ProjectModel.BuildSettings.SingleValueSetting {
1067+
init?(from declaration: PackageModel.BuildSettings.Declaration) {
1068+
switch declaration {
1069+
case .SWIFT_VERSION:
1070+
self = .SWIFT_VERSION
1071+
default:
1072+
return nil
1073+
}
1074+
}
1075+
}
1076+
1077+
extension ProjectModel.BuildSettings.MultipleValueSetting {
1078+
init?(from declaration: PackageModel.BuildSettings.Declaration) {
1079+
switch declaration {
10681080
case .SWIFT_ACTIVE_COMPILATION_CONDITIONS:
1069-
.SWIFT_ACTIVE_COMPILATION_CONDITIONS
1081+
self = .SWIFT_ACTIVE_COMPILATION_CONDITIONS
10701082
case .OTHER_SWIFT_FLAGS:
1071-
.OTHER_SWIFT_FLAGS
1072-
case .SWIFT_VERSION:
1073-
.SWIFT_VERSION
1074-
// C family.
1083+
self = .OTHER_SWIFT_FLAGS
10751084
case .GCC_PREPROCESSOR_DEFINITIONS:
1076-
.GCC_PREPROCESSOR_DEFINITIONS
1085+
self = .GCC_PREPROCESSOR_DEFINITIONS
10771086
case .HEADER_SEARCH_PATHS:
1078-
.HEADER_SEARCH_PATHS
1087+
self = .HEADER_SEARCH_PATHS
10791088
case .OTHER_CFLAGS:
1080-
.OTHER_CFLAGS
1089+
self = .OTHER_CFLAGS
10811090
case .OTHER_CPLUSPLUSFLAGS:
1082-
.OTHER_CPLUSPLUSFLAGS
1083-
// Linker.
1091+
self = .OTHER_CPLUSPLUSFLAGS
10841092
case .OTHER_LDFLAGS:
1085-
.OTHER_LDFLAGS
1086-
case .LINK_LIBRARIES, .LINK_FRAMEWORKS:
1087-
preconditionFailure("Should not be reached")
1093+
self = .OTHER_LDFLAGS
10881094
default:
1089-
preconditionFailure("Unexpected BuildSettings.Declaration: \(declaration.name)")
1095+
return nil
10901096
}
10911097
}
10921098
}

Sources/SwiftBuildSupport/PackagePIFBuilder.swift

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -516,16 +516,16 @@ public final class PackagePIFBuilder {
516516
settings[.MACOSX_DEPLOYMENT_TARGET] = builder.deploymentTargets[.macOS] ?? nil
517517
settings[.IPHONEOS_DEPLOYMENT_TARGET] = builder.deploymentTargets[.iOS] ?? nil
518518
if let deploymentTarget_macCatalyst = builder.deploymentTargets[.macCatalyst] ?? nil {
519-
settings
520-
.platformSpecificSettings[.macCatalyst]![.IPHONEOS_DEPLOYMENT_TARGET] = [deploymentTarget_macCatalyst]
519+
settings[.IPHONEOS_DEPLOYMENT_TARGET, .macCatalyst] = deploymentTarget_macCatalyst
521520
}
522521
settings[.TVOS_DEPLOYMENT_TARGET] = builder.deploymentTargets[.tvOS] ?? nil
523522
settings[.WATCHOS_DEPLOYMENT_TARGET] = builder.deploymentTargets[.watchOS] ?? nil
524523
settings[.DRIVERKIT_DEPLOYMENT_TARGET] = builder.deploymentTargets[.driverKit] ?? nil
525524
settings[.XROS_DEPLOYMENT_TARGET] = builder.deploymentTargets[.visionOS] ?? nil
526525

527-
for machoPlatform in [ProjectModel.BuildSettings.Platform.macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .xrOS, .driverKit] {
528-
settings.platformSpecificSettings[machoPlatform]![.DYLIB_INSTALL_NAME_BASE]! = ["@rpath"]
526+
for machoPlatform: ProjectModel.BuildSettings.Platform in [ProjectModel.BuildSettings.Platform.macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .xrOS, .driverKit] {
527+
settings[.DYLIB_INSTALL_NAME_BASE, machoPlatform] = "@rpath"
528+
settings[.CLANG_ENABLE_MODULES, machoPlatform] = "YES"
529529
}
530530

531531
settings[.USE_HEADERMAP] = "NO"
@@ -566,8 +566,7 @@ public final class PackagePIFBuilder {
566566
log(.warning, "Ignoring options '\(platformOptions.joined(separator: " "))' specified for unknown platform \(platform.name)")
567567
continue
568568
}
569-
settings.platformSpecificSettings[pifPlatform]![.SPECIALIZATION_SDK_OPTIONS]!
570-
.append(contentsOf: platformOptions)
569+
settings[.SPECIALIZATION_SDK_OPTIONS, pifPlatform]?.append(contentsOf: platformOptions)
571570
}
572571

573572
let deviceFamilyIDs: Set<Int> = self.delegate.deviceFamilyIDs()
@@ -593,7 +592,7 @@ public final class PackagePIFBuilder {
593592
} catch {
594593
preconditionFailure("Unhandled arm64e platform: \(error)")
595594
}
596-
settings.platformSpecificSettings[pifPlatform]![.ARCHS, default: []].append(contentsOf: ["arm64e"])
595+
settings[.ARCHS, pifPlatform]?.append(contentsOf: ["arm64e"])
597596
}
598597
}
599598

0 commit comments

Comments
 (0)