Skip to content

Commit 2899598

Browse files
WIP - implement inheritance
1 parent 0f6abcc commit 2899598

7 files changed

Lines changed: 312 additions & 688 deletions

File tree

Sources/PackageLoading/ManifestJSONParser.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,8 @@ extension TargetBuildSettingDescription.Kind {
811811
}
812812

813813
return .defaultIsolation(isolation)
814+
case "inherited":
815+
return .inherited
814816
default:
815817
throw InternalError("invalid build setting \(name)")
816818
}

Sources/PackageLoading/PackageBuilder.swift

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,9 +1086,36 @@ public final class PackageBuilder {
10861086
}
10871087
}
10881088

1089-
private func resolvedSettings(for target: TargetDescription) -> [TargetBuildSettingDescription.Setting] {
1090-
var resolved = target.settings
1089+
private func resolvedSettings(for target: TargetDescription) throws -> [TargetBuildSettingDescription.Setting] {
1090+
var resolved: [TargetBuildSettingDescription.Setting] = []
1091+
1092+
// first, validate defaults
1093+
for setting in manifest.defaultSettings ?? [] {
1094+
if case .unsafeFlags = setting.kind {
1095+
throw ModuleError.invalidManifestConfig(
1096+
self.identity.description, "default settings cannot contain unsafe flags"
1097+
)
1098+
}
1099+
}
1100+
1101+
// copy over all existing settings, substituting in defaults if inherited is encountered.
1102+
for setting in target.settings {
1103+
switch setting.kind {
1104+
case .inherited:
1105+
if setting.condition != nil {
1106+
throw ModuleError.invalidManifestConfig(
1107+
self.identity.description, "inherited settings cannot use conditions"
1108+
)
1109+
}
10911110

1111+
let defaults = manifest.defaultSettings?.filter({ $0.tool == setting.tool }) ?? []
1112+
resolved.append(contentsOf: defaults)
1113+
default:
1114+
resolved.append(setting)
1115+
}
1116+
}
1117+
1118+
// Now, apply the defaults if nothing explicit is present.
10921119
if !target.explicitSettings.swift {
10931120
resolved.append(contentsOf: manifest.defaultSettings?.filter({ $0.tool == .swift }) ?? [])
10941121
}
@@ -1105,25 +1132,6 @@ public final class PackageBuilder {
11051132
resolved.append(contentsOf: manifest.defaultSettings?.filter({ $0.tool == .linker }) ?? [])
11061133
}
11071134

1108-
// let defaultSettings = manifest.defaultSettings ?? []
1109-
//
1110-
// for defaultSetting in defaultSettings {
1111-
// var eligible = true
1112-
//
1113-
// // Look for an existing target setting that takes precedence. If none are found,
1114-
// // the default is accepted.
1115-
// for setting in resolved {
1116-
// if setting.overridesDefault(defaultSetting) {
1117-
// eligible = false
1118-
// break
1119-
// }
1120-
// }
1121-
//
1122-
// if eligible {
1123-
// resolved.append(defaultSetting)
1124-
// }
1125-
// }
1126-
//
11271135
return resolved
11281136
}
11291137

@@ -1144,7 +1152,7 @@ public final class PackageBuilder {
11441152
table.add(versionAssignment, for: .SWIFT_VERSION)
11451153

11461154
// Process each setting.
1147-
for setting in resolvedSettings(for: target) {
1155+
for setting in try resolvedSettings(for: target) {
11481156
if let traits = setting.condition?.traits, traits.intersection(self.enabledTraits.names).isEmpty {
11491157
// The setting is currently not enabled so we should skip it
11501158
continue
@@ -1382,6 +1390,8 @@ public final class PackageBuilder {
13821390
}
13831391

13841392
values = ["-default-isolation", isolation.rawValue]
1393+
case .inherited:
1394+
throw InternalError("inherited cannot be in resolved setttings")
13851395
}
13861396

13871397
// Create an assignment for this setting.

Sources/PackageModel/Manifest/TargetBuildSettingDescription.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,16 @@ public enum TargetBuildSettingDescription {
6060

6161
case defaultIsolation(DefaultIsolation)
6262

63+
case inherited
64+
6365
public var isUnsafeFlags: Bool {
6466
switch self {
6567
case .unsafeFlags(let flags):
6668
// If `.unsafeFlags` is used, but doesn't specify any flags, we treat it the same way as not specifying it.
6769
return !flags.isEmpty
6870
case .headerSearchPath, .define, .linkedLibrary, .linkedFramework, .interoperabilityMode,
6971
.enableUpcomingFeature, .enableExperimentalFeature, .strictMemorySafety, .swiftLanguageMode,
70-
.treatAllWarnings, .treatWarning, .enableWarning, .disableWarning, .defaultIsolation:
72+
.treatAllWarnings, .treatWarning, .enableWarning, .disableWarning, .defaultIsolation, .inherited:
7173
return false
7274
}
7375
}

Sources/PackageModel/Manifest/TargetDescription.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,43 @@ public struct TargetDescription: Hashable, Encodable, Sendable {
463463
) }
464464
}
465465

466+
// ensure that settings and settings presense detection are consistent
467+
if settings.filter({ $0.tool == .swift}).isEmpty == false && explicitSettings.swift == false {
468+
throw Error.disallowedPropertyInTarget(
469+
targetName: name,
470+
targetType: targetType,
471+
propertyName: "explicitSettings",
472+
value: "swift"
473+
)
474+
}
475+
476+
if settings.filter({ $0.tool == .c}).isEmpty == false && explicitSettings.c == false {
477+
throw Error.disallowedPropertyInTarget(
478+
targetName: name,
479+
targetType: targetType,
480+
propertyName: "explicitSettings",
481+
value: "c"
482+
)
483+
}
484+
485+
if settings.filter({ $0.tool == .cxx}).isEmpty == false && explicitSettings.cxx == false {
486+
throw Error.disallowedPropertyInTarget(
487+
targetName: name,
488+
targetType: targetType,
489+
propertyName: "explicitSettings",
490+
value: "cxx"
491+
)
492+
}
493+
494+
if settings.filter({ $0.tool == .linker}).isEmpty == false && explicitSettings.linker == false {
495+
throw Error.disallowedPropertyInTarget(
496+
targetName: name,
497+
targetType: targetType,
498+
propertyName: "explicitSettings",
499+
value: "linker"
500+
)
501+
}
502+
466503
self.name = name
467504
self.dependencies = dependencies
468505
self.path = path

Sources/PackageModel/ManifestSourceGeneration.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,8 @@ fileprivate extension SourceCodeFragment {
727727
params.append(SourceCodeFragment(from: condition))
728728
}
729729
self.init(enum: setting.kind.name, subnodes: params)
730+
case .inherited:
731+
self.init(enum: setting.kind.name, subnodes: [])
730732
}
731733
}
732734

@@ -1215,6 +1217,8 @@ extension TargetBuildSettingDescription.Kind {
12151217
return "disableWarning"
12161218
case .defaultIsolation:
12171219
return "defaultIsolation"
1220+
case .inherited:
1221+
return "inherited"
12181222
}
12191223
}
12201224
}

Sources/Runtimes/PackageDescription/BuildSettings.swift

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,20 @@ public struct CSetting: Sendable {
289289
return CSetting(
290290
name: "disableWarning", value: [name], condition: condition)
291291
}
292+
293+
/// Inherit default settings.
294+
///
295+
/// - Since: First available in PackageDescription 6.5.
296+
///
297+
/// This setting is a placeholder that will be substituted with any value set by `defaultCSettings`.
298+
@available(_PackageDescription, introduced: 6.2)
299+
public static func inherited() -> CSetting {
300+
return CSetting(
301+
name: "inherited",
302+
value: ["placeholder"],
303+
condition: nil
304+
)
305+
}
292306
}
293307

294308
/// A CXX-language build setting.
@@ -445,6 +459,20 @@ public struct CXXSetting: Sendable {
445459
return CXXSetting(
446460
name: "disableWarning", value: [name], condition: condition)
447461
}
462+
463+
/// Inherit default settings.
464+
///
465+
/// - Since: First available in PackageDescription 6.5.
466+
///
467+
/// This setting is a placeholder that will be substituted with any value set by `defaultCXXSettings`.
468+
@available(_PackageDescription, introduced: 6.2)
469+
public static func inherited() -> CXXSetting {
470+
return CXXSetting(
471+
name: "inherited",
472+
value: ["placeholder"],
473+
condition: nil
474+
)
475+
}
448476
}
449477

450478
/// A Swift language build setting.
@@ -714,6 +742,20 @@ public struct SwiftSetting: Sendable {
714742
return SwiftSetting(
715743
name: "defaultIsolation", value: [isolationString], condition: condition)
716744
}
745+
746+
/// Inherit default settings.
747+
///
748+
/// - Since: First available in PackageDescription 6.5.
749+
///
750+
/// This setting is a placeholder that will be substituted with any value set by `defaultSwiftSettings`.
751+
@available(_PackageDescription, introduced: 6.2)
752+
public static func inherited() -> SwiftSetting {
753+
return SwiftSetting(
754+
name: "inherited",
755+
value: ["placeholder"],
756+
condition: nil
757+
)
758+
}
717759
}
718760

719761
/// A linker build setting.
@@ -778,4 +820,18 @@ public struct LinkerSetting: Sendable {
778820
public static func unsafeFlags(_ flags: [String], _ condition: BuildSettingCondition? = nil) -> LinkerSetting {
779821
return LinkerSetting(name: "unsafeFlags", value: flags, condition: condition)
780822
}
823+
824+
/// Inherit default settings.
825+
///
826+
/// - Since: First available in PackageDescription 6.5.
827+
///
828+
/// This setting is a placeholder that will be substituted with any value set by `defaultLinkerSettings`.
829+
@available(_PackageDescription, introduced: 6.2)
830+
public static func inherited() -> LinkerSetting {
831+
return LinkerSetting(
832+
name: "inherited",
833+
value: ["placeholder"],
834+
condition: nil
835+
)
836+
}
781837
}

0 commit comments

Comments
 (0)