Skip to content

Commit 1212f9b

Browse files
authored
refactor target build settings model (#4171)
motivation: as part of auditing the code for preconditions and assets it came to light that the target build setting model can be improved to handle preconditions via the type system changes: * move the build settings values into the build setting kind enum as associated values (instead of floating attribute) * adjust call sites and test
1 parent c7eef11 commit 1212f9b

File tree

14 files changed

+177
-163
lines changed

14 files changed

+177
-163
lines changed

Sources/PackageLoading/ManifestJSONParser.swift

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -377,26 +377,53 @@ enum ManifestJSONParser {
377377
try Self.parseBuildSetting($0, tool: tool)
378378
})
379379
}
380-
380+
381381
private static func parseBuildSetting(_ json: JSON, tool: TargetBuildSettingDescription.Tool) throws -> TargetBuildSettingDescription.Setting {
382382
let json = try json.getJSON("data")
383-
let name = try TargetBuildSettingDescription.SettingName(rawValue: json.get("name"))!
383+
let name = try json.get(String.self, forKey: "name")
384+
let values = try json.get([String].self, forKey: "value")
384385
let condition = try (try? json.getJSON("condition")).flatMap(PackageConditionDescription.init(v4:))
385-
386-
let value = try json.get([String].self, forKey: "value")
387-
386+
388387
// Diagnose invalid values.
389-
for item in value {
388+
for item in values {
390389
let groups = Self.invalidValueRegex.matchGroups(in: item).flatMap{ $0 }
391390
if !groups.isEmpty {
392391
let error = "the build setting '\(name)' contains invalid component(s): \(groups.joined(separator: " "))"
393392
throw ManifestParseError.runtimeManifestErrors([error])
394393
}
395394
}
396-
395+
396+
let kind: TargetBuildSettingDescription.Kind
397+
switch name {
398+
case "headerSearchPath":
399+
guard let value = values.first else {
400+
throw InternalError("invalid (empty) build settings value")
401+
}
402+
kind = .headerSearchPath(value)
403+
case "define":
404+
guard let value = values.first else {
405+
throw InternalError("invalid (empty) build settings value")
406+
}
407+
kind = .define(value)
408+
case "linkedLibrary":
409+
guard let value = values.first else {
410+
throw InternalError("invalid (empty) build settings value")
411+
}
412+
kind = .linkedLibrary(value)
413+
case "linkedFramework":
414+
guard let value = values.first else {
415+
throw InternalError("invalid (empty) build settings value")
416+
}
417+
kind = .linkedFramework(value)
418+
case "unsafeFlags":
419+
kind = .unsafeFlags(values)
420+
default:
421+
throw InternalError("invalid build setting \(name)")
422+
}
423+
397424
return .init(
398-
tool: tool, name: name,
399-
value: value,
425+
tool: tool,
426+
kind: kind,
400427
condition: condition
401428
)
402429
}

Sources/PackageLoading/PackageBuilder.swift

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -917,10 +917,12 @@ public final class PackageBuilder {
917917
// Process each setting.
918918
for setting in target.settings {
919919
let decl: BuildSettings.Declaration
920+
let values: [String]
920921

921922
// Compute appropriate declaration for the setting.
922-
switch setting.name {
923-
case .headerSearchPath:
923+
switch setting.kind {
924+
case .headerSearchPath(let value):
925+
values = [value]
924926

925927
switch setting.tool {
926928
case .c, .cxx:
@@ -930,12 +932,14 @@ public final class PackageBuilder {
930932
}
931933

932934
// Ensure that the search path is contained within the package.
933-
let subpath = try RelativePath(validating: setting.value[0])
935+
let subpath = try RelativePath(validating: value)
934936
guard targetRoot.appending(subpath).isDescendantOfOrEqual(to: packagePath) else {
935937
throw ModuleError.invalidHeaderSearchPath(subpath.pathString)
936938
}
937939

938-
case .define:
940+
case .define(let value):
941+
values = [value]
942+
939943
switch setting.tool {
940944
case .c, .cxx:
941945
decl = .GCC_PREPROCESSOR_DEFINITIONS
@@ -945,23 +949,29 @@ public final class PackageBuilder {
945949
throw InternalError("unexpected tool for setting type \(setting)")
946950
}
947951

948-
case .linkedLibrary:
952+
case .linkedLibrary(let value):
953+
values = [value]
954+
949955
switch setting.tool {
950956
case .c, .cxx, .swift:
951957
throw InternalError("unexpected tool for setting type \(setting)")
952958
case .linker:
953959
decl = .LINK_LIBRARIES
954960
}
955961

956-
case .linkedFramework:
962+
case .linkedFramework(let value):
963+
values = [value]
964+
957965
switch setting.tool {
958966
case .c, .cxx, .swift:
959967
throw InternalError("unexpected tool for setting type \(setting)")
960968
case .linker:
961969
decl = .LINK_FRAMEWORKS
962970
}
963971

964-
case .unsafeFlags:
972+
case .unsafeFlags(let _values):
973+
values = _values
974+
965975
switch setting.tool {
966976
case .c:
967977
decl = .OTHER_CFLAGS
@@ -976,7 +986,7 @@ public final class PackageBuilder {
976986

977987
// Create an assignment for this setting.
978988
var assignment = BuildSettings.Assignment()
979-
assignment.value = setting.value
989+
assignment.values = values
980990
assignment.conditions = buildConditions(from: setting.condition)
981991

982992
// Finally, add the assignment to the assignment table.

Sources/PackageModel/BuildSettings.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public enum BuildSettings {
4646
/// An individual build setting assignment.
4747
public struct Assignment: Codable {
4848
/// The assignment value.
49-
public var value: [String]
49+
public var values: [String]
5050

5151
// FIXME: This should be a set but we need Equatable existential (or AnyEquatable) for that.
5252
/// The condition associated with this assignment.
@@ -63,7 +63,7 @@ public enum BuildSettings {
6363

6464
public init() {
6565
self._conditions = []
66-
self.value = []
66+
self.values = []
6767
}
6868
}
6969

@@ -108,7 +108,7 @@ public enum BuildSettings {
108108
let values = assignments
109109
.lazy
110110
.filter { $0.conditions.allSatisfy { $0.satisfies(self.environment) } }
111-
.flatMap { $0.value }
111+
.flatMap { $0.values }
112112

113113
return Array(values)
114114
}

Sources/PackageModel/Manifest/TargetBuildSettingDescription.swift

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ public enum TargetBuildSettingDescription {
1919
case linker
2020
}
2121

22-
/// The name of the build setting.
23-
public enum SettingName: String, Codable, Equatable {
24-
case headerSearchPath
25-
case define
26-
case linkedLibrary
27-
case linkedFramework
28-
29-
case unsafeFlags
22+
/// The kind of the build setting, with associate configuration
23+
public enum Kind: Codable, Equatable {
24+
case headerSearchPath(String)
25+
case define(String)
26+
case linkedLibrary(String)
27+
case linkedFramework(String)
28+
29+
case unsafeFlags([String])
3030
}
3131

3232
/// An individual build setting.
@@ -35,38 +35,19 @@ public enum TargetBuildSettingDescription {
3535
/// The tool associated with this setting.
3636
public let tool: Tool
3737

38-
/// The name of the setting.
39-
public let name: SettingName
38+
/// The kind of the setting.
39+
public let kind: Kind
4040

4141
/// The condition at which the setting should be applied.
4242
public let condition: PackageConditionDescription?
4343

44-
/// The value of the setting.
45-
///
46-
/// This is kind of like an "untyped" value since the length
47-
/// of the array will depend on the setting type.
48-
public let value: [String]
49-
5044
public init(
5145
tool: Tool,
52-
name: SettingName,
53-
value: [String],
54-
condition: PackageConditionDescription? = nil
46+
kind: Kind,
47+
condition: PackageConditionDescription? = .none
5548
) {
56-
switch name {
57-
case .headerSearchPath: fallthrough
58-
case .define: fallthrough
59-
case .linkedLibrary: fallthrough
60-
case .linkedFramework:
61-
assert(value.count == 1, "\(tool) \(name) \(value)")
62-
break
63-
case .unsafeFlags:
64-
break
65-
}
66-
6749
self.tool = tool
68-
self.name = name
69-
self.value = value
50+
self.kind = kind
7051
self.condition = condition
7152
}
7253
}

Sources/PackageModel/ManifestSourceGeneration.swift

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -458,17 +458,15 @@ fileprivate extension SourceCodeFragment {
458458
init(from setting: TargetBuildSettingDescription.Setting) {
459459
var params: [SourceCodeFragment] = []
460460

461-
switch setting.name {
462-
case .headerSearchPath, .linkedLibrary, .linkedFramework:
463-
assert(setting.value.count == 1)
464-
params.append(SourceCodeFragment(string: setting.value[0]))
461+
switch setting.kind {
462+
case .headerSearchPath(let value), .linkedLibrary(let value), .linkedFramework(let value):
463+
params.append(SourceCodeFragment(string: value))
465464
if let condition = setting.condition {
466465
params.append(SourceCodeFragment(from: condition))
467466
}
468-
self.init(enum: setting.name.rawValue, subnodes: params)
469-
case .define:
470-
assert(setting.value.count == 1)
471-
let parts = setting.value[0].split(separator: "=", maxSplits: 1)
467+
self.init(enum: setting.kind.name, subnodes: params)
468+
case .define(let value):
469+
let parts = value.split(separator: "=", maxSplits: 1)
472470
assert(parts.count == 1 || parts.count == 2)
473471
params.append(SourceCodeFragment(string: String(parts[0])))
474472
if parts.count == 2 {
@@ -477,13 +475,13 @@ fileprivate extension SourceCodeFragment {
477475
if let condition = setting.condition {
478476
params.append(SourceCodeFragment(from: condition))
479477
}
480-
self.init(enum: setting.name.rawValue, subnodes: params)
481-
case .unsafeFlags:
482-
params.append(SourceCodeFragment(strings: setting.value))
478+
self.init(enum: setting.kind.name, subnodes: params)
479+
case .unsafeFlags(let values):
480+
params.append(SourceCodeFragment(strings: values))
483481
if let condition = setting.condition {
484482
params.append(SourceCodeFragment(from: condition))
485483
}
486-
self.init(enum: setting.name.rawValue, subnodes: params)
484+
self.init(enum: setting.kind.name, subnodes: params)
487485
}
488486
}
489487
}
@@ -617,10 +615,25 @@ public struct SourceCodeFragment {
617615
}
618616
}
619617

618+
extension TargetBuildSettingDescription.Kind {
619+
fileprivate var name: String {
620+
switch self {
621+
case .headerSearchPath:
622+
return "headerSearchPath"
623+
case .define:
624+
return "define"
625+
case .linkedLibrary:
626+
return "linkedLibrary"
627+
case .linkedFramework:
628+
return "linkedFramework"
629+
case .unsafeFlags:
630+
return "unsafeFlags"
631+
}
632+
}
633+
}
620634

621-
fileprivate extension String {
622-
623-
var quotedForPackageManifest: String {
635+
extension String {
636+
fileprivate var quotedForPackageManifest: String {
624637
return "\"" + self
625638
.replacingOccurrences(of: "\\", with: "\\\\")
626639
.replacingOccurrences(of: "\"", with: "\\\"")

Sources/XCBuildSupport/PIFBuilder.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,16 +1440,16 @@ private extension BuildSettings.AssignmentTable {
14401440
switch declaration {
14411441
case .LINK_LIBRARIES:
14421442
setting = .OTHER_LDFLAGS
1443-
value = assignment.value.map { "-l\($0)" }
1443+
value = assignment.values.map { "-l\($0)" }
14441444
case .LINK_FRAMEWORKS:
14451445
setting = .OTHER_LDFLAGS
1446-
value = assignment.value.flatMap { ["-framework", $0] }
1446+
value = assignment.values.flatMap { ["-framework", $0] }
14471447
default:
14481448
guard let parsedSetting = PIF.BuildSettings.MultipleValueSetting(rawValue: declaration.name) else {
14491449
continue
14501450
}
14511451
setting = parsedSetting
1452-
value = assignment.value
1452+
value = assignment.values
14531453
}
14541454

14551455
let pifAssignment = PIFBuildSettingAssignment(

Sources/Xcodeproj/pbxproj.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ public func xcodeProject(
632632
}
633633
}
634634
let config = assignment.conditions.compactMap { $0 as? ConfigurationCondition }.first?.configuration
635-
try appendSetting(assignment.value, forDecl: decl, to: xcodeTarget.buildSettings, config: config)
635+
try appendSetting(assignment.values, forDecl: decl, to: xcodeTarget.buildSettings, config: config)
636636
}
637637
}
638638
}

0 commit comments

Comments
 (0)