Skip to content

Commit cf4866a

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 cf4866a

File tree

6 files changed

+163
-181
lines changed

6 files changed

+163
-181
lines changed

Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift

Lines changed: 139 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -524,14 +524,100 @@ 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+
// Initialize all platforms with ["$(inherited)"] for each used multiple-value setting
572+
for setting in usedMultipleValueSettings {
573+
for platform in ProjectModel.BuildSettings.Platform.allCases {
574+
if buildSettings[setting, platform] == nil {
575+
buildSettings[setting, platform] = ["$(inherited)"]
576+
}
577+
}
578+
}
579+
580+
// Now apply the platform-specific values
581+
for (platform, multipleValues) in multipleValuesByPlatform {
582+
for (setting, values) in multipleValues {
583+
if let platform = platform {
584+
// Get existing values (should now be initialized with inherited)
585+
let existingValues = buildSettings[setting, platform] ?? ["$(inherited)"]
586+
buildSettings[setting, platform] = existingValues + values
587+
} else {
588+
// Append to existing values instead of overwriting
589+
let existingValues = buildSettings[setting] ?? ["$(inherited)"]
590+
buildSettings[setting] = existingValues + values
591+
}
592+
}
593+
}
594+
}
595+
}
596+
597+
/// Apply imparted settings to a ProjectModel.BuildSettings instance
598+
func applyImparted(to buildSettings: inout ProjectModel.BuildSettings) {
599+
// Apply imparted single value settings for all platforms
600+
for (platform, singleValues) in impartedSingleValueSettings {
601+
for (setting, value) in singleValues {
602+
if let platform = platform {
603+
buildSettings[setting, platform] = value
604+
} else {
605+
buildSettings[setting] = value
606+
}
607+
}
608+
}
609+
610+
// Apply imparted multiple value settings for all platforms
611+
for (platform, multipleValues) in impartedMultipleValueSettings {
612+
for (setting, values) in multipleValues {
613+
if let platform = platform {
614+
buildSettings[setting, platform] = values
615+
} else {
616+
buildSettings[setting] = values
617+
}
618+
}
619+
}
620+
}
535621
}
536622

537623
/// Target-specific build settings declared in the manifest and that apply to the target itself.
@@ -546,20 +632,31 @@ extension PackageGraph.ResolvedModule {
546632
for settingAssignment in settingsAssigments {
547633
// Create a build setting value; in some cases there
548634
// isn't a direct mapping to Swift Build build settings.
549-
let pifDeclaration: BuildSettings.Declaration
550635
let values: [String]
636+
let singleValueSetting: ProjectModel.BuildSettings.SingleValueSetting?
637+
let multipleValueSetting: ProjectModel.BuildSettings.MultipleValueSetting?
638+
551639
switch declaration {
552640
case .LINK_FRAMEWORKS:
553-
pifDeclaration = .OTHER_LDFLAGS
641+
singleValueSetting = nil
642+
multipleValueSetting = .OTHER_LDFLAGS
554643
values = settingAssignment.values.flatMap { ["-framework", $0] }
555644
case .LINK_LIBRARIES:
556-
pifDeclaration = .OTHER_LDFLAGS
645+
singleValueSetting = nil
646+
multipleValueSetting = .OTHER_LDFLAGS
557647
values = settingAssignment.values.map { "-l\($0)" }
558648
case .HEADER_SEARCH_PATHS:
559-
pifDeclaration = .HEADER_SEARCH_PATHS
649+
singleValueSetting = nil
650+
multipleValueSetting = .HEADER_SEARCH_PATHS
560651
values = settingAssignment.values.map { self.sourceDirAbsolutePath.pathString + "/" + $0 }
561652
default:
562-
pifDeclaration = ProjectModel.BuildSettings.Declaration(from: declaration)
653+
if declaration.allowsMultipleValues {
654+
singleValueSetting = nil
655+
multipleValueSetting = ProjectModel.BuildSettings.MultipleValueSetting(from: declaration)
656+
} else {
657+
singleValueSetting = ProjectModel.BuildSettings.SingleValueSetting(from: declaration)
658+
multipleValueSetting = nil
659+
}
563660
values = settingAssignment.values
564661
}
565662

@@ -578,26 +675,19 @@ extension PackageGraph.ResolvedModule {
578675
pifPlatform = nil
579676
}
580677

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
678+
// Handle imparted settings for OTHER_LDFLAGS (always multiple values)
679+
if let multipleValueSetting = multipleValueSetting, multipleValueSetting == .OTHER_LDFLAGS {
680+
allSettings.impartedMultipleValueSettings[pifPlatform, default: [:]][multipleValueSetting, default: []].append(contentsOf: values)
588681
}
589682

590683
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] } ?? []
684+
if let multipleValueSetting = multipleValueSetting {
685+
// Handle multiple value settings
686+
allSettings.targetMultipleValueSettings[configuration, default: [:]][pifPlatform, default: [:]][multipleValueSetting, default: []].append(contentsOf: values)
687+
} else if let singleValueSetting = singleValueSetting, let singleValue = values.only {
688+
// Handle single value settings
689+
allSettings.targetSingleValueSettings[configuration, default: [:]][pifPlatform, default: [:]][singleValueSetting] = singleValue
598690
}
599-
600-
allSettings.targetSettings[configuration, default: [:]][pifPlatform] = settingsByDeclaration
601691
}
602692
}
603693
}
@@ -911,88 +1001,8 @@ extension ProjectModel.BuildSettings {
9111001
/// Note that this restricts the settings that can be set by this function to those that can have platform-specific
9121002
/// values, i.e. those in `ProjectModel.BuildSettings.Declaration`. If a platform is specified,
9131003
/// 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-
}
9651004
}
9661005

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-
}
9961006

9971007
extension ProjectModel.BuildSettings.Platform {
9981008
enum Error: Swift.Error {
@@ -1034,7 +1044,6 @@ extension ProjectModel.BuildSettings {
10341044
self[.PRODUCT_NAME] = productName
10351045
self[.PRODUCT_MODULE_NAME] = productName
10361046
self[.PRODUCT_BUNDLE_IDENTIFIER] = "\(packageIdentity).\(productName)".spm_mangledToBundleIdentifier()
1037-
self[.CLANG_ENABLE_MODULES] = "YES"
10381047
self[.SWIFT_PACKAGE_NAME] = packageName ?? nil
10391048

10401049
if !createDylibForDynamicProducts {
@@ -1061,32 +1070,36 @@ extension ProjectModel.BuildSettings {
10611070
}
10621071
}
10631072

1064-
extension ProjectModel.BuildSettings.Declaration {
1065-
init(from declaration: PackageModel.BuildSettings.Declaration) {
1066-
self = switch declaration {
1067-
// Swift.
1073+
extension ProjectModel.BuildSettings.SingleValueSetting {
1074+
init?(from declaration: PackageModel.BuildSettings.Declaration) {
1075+
switch declaration {
1076+
case .SWIFT_VERSION:
1077+
self = .SWIFT_VERSION
1078+
default:
1079+
return nil
1080+
}
1081+
}
1082+
}
1083+
1084+
extension ProjectModel.BuildSettings.MultipleValueSetting {
1085+
init?(from declaration: PackageModel.BuildSettings.Declaration) {
1086+
switch declaration {
10681087
case .SWIFT_ACTIVE_COMPILATION_CONDITIONS:
1069-
.SWIFT_ACTIVE_COMPILATION_CONDITIONS
1088+
self = .SWIFT_ACTIVE_COMPILATION_CONDITIONS
10701089
case .OTHER_SWIFT_FLAGS:
1071-
.OTHER_SWIFT_FLAGS
1072-
case .SWIFT_VERSION:
1073-
.SWIFT_VERSION
1074-
// C family.
1090+
self = .OTHER_SWIFT_FLAGS
10751091
case .GCC_PREPROCESSOR_DEFINITIONS:
1076-
.GCC_PREPROCESSOR_DEFINITIONS
1092+
self = .GCC_PREPROCESSOR_DEFINITIONS
10771093
case .HEADER_SEARCH_PATHS:
1078-
.HEADER_SEARCH_PATHS
1094+
self = .HEADER_SEARCH_PATHS
10791095
case .OTHER_CFLAGS:
1080-
.OTHER_CFLAGS
1096+
self = .OTHER_CFLAGS
10811097
case .OTHER_CPLUSPLUSFLAGS:
1082-
.OTHER_CPLUSPLUSFLAGS
1083-
// Linker.
1098+
self = .OTHER_CPLUSPLUSFLAGS
10841099
case .OTHER_LDFLAGS:
1085-
.OTHER_LDFLAGS
1086-
case .LINK_LIBRARIES, .LINK_FRAMEWORKS:
1087-
preconditionFailure("Should not be reached")
1100+
self = .OTHER_LDFLAGS
10881101
default:
1089-
preconditionFailure("Unexpected BuildSettings.Declaration: \(declaration.name)")
1102+
return nil
10901103
}
10911104
}
10921105
}

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)