Skip to content

Commit 570e1c2

Browse files
author
Luke Daley
committed
Simplify implementation of dependency verification dynamic default
1 parent 031f046 commit 570e1c2

File tree

5 files changed

+70
-34
lines changed

5 files changed

+70
-34
lines changed

Sources/SWBCore/Dependencies.swift

+6-11
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ public import SWBMacro
1616
import Foundation
1717

1818
// Global/target dependency settings
19-
public struct DependencySettings : Serializable, Sendable, Encodable {
20-
public let dependencies: OrderedSet<String>
19+
public struct DependencySettings: Serializable, Sendable, Encodable {
20+
public let dependencies: [String] // lexicographically ordered and uniqued
2121
public let verification: Bool
2222

2323
public init(
2424
dependencies: any Sequence<String>,
2525
verification: Bool
2626
) {
27-
self.dependencies = OrderedSet(dependencies)
27+
self.dependencies = Array(OrderedSet(dependencies).sorted())
2828
self.verification = verification
2929
}
3030

@@ -45,21 +45,16 @@ public struct DependencySettings : Serializable, Sendable, Encodable {
4545
extension DependencySettings {
4646
public init(_ scope: MacroEvaluationScope) {
4747
let dependencies = scope.evaluate(BuiltinMacros.DEPENDENCIES)
48-
49-
// We cannot distinguish between "DEPENDENCIES" not set and set to an empty list.
50-
// Turn verification off it we have an empty list, assuming that it is not set.
51-
// This means that there is no way at the moment to declare that a project with no dependencies should have verification enabled.
52-
let verification = !dependencies.isEmpty && scope.evaluate(BuiltinMacros.DEPENDENCIES_VERIFICATION)
53-
5448
self.init(
5549
dependencies: dependencies,
56-
verification: verification
50+
verification: scope.evaluate(BuiltinMacros.DEPENDENCIES_VERIFICATION)
51+
.isEnabled(onNotSet: !dependencies.isEmpty),
5752
)
5853
}
5954
}
6055

6156
// Task-specific settings
62-
public struct TaskDependencySettings : Serializable, Sendable, Encodable {
57+
public struct TaskDependencySettings: Serializable, Sendable, Encodable {
6358

6459
public let traceFile: Path
6560
public let dependencySettings: DependencySettings

Sources/SWBCore/Settings/BuiltinMacros.swift

+20-1
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ public final class BuiltinMacros {
586586
public static let DEFAULT_KEXT_INSTALL_PATH = BuiltinMacros.declareStringMacro("DEFAULT_KEXT_INSTALL_PATH")
587587
public static let DEFINES_MODULE = BuiltinMacros.declareBooleanMacro("DEFINES_MODULE")
588588
public static let DEPENDENCIES = BuiltinMacros.declareStringListMacro("DEPENDENCIES")
589-
public static let DEPENDENCIES_VERIFICATION = BuiltinMacros.declareBooleanMacro("DEPENDENCIES_VERIFICATION")
589+
public static let DEPENDENCIES_VERIFICATION = BuiltinMacros.declareEnumMacro("DEPENDENCIES_VERIFICATION") as EnumMacroDeclaration<DependenciesVerificationSetting>
590590
public static let DEPENDENCY_SCOPE_INCLUDES_DIRECT_DEPENDENCIES = BuiltinMacros.declareBooleanMacro("DEPENDENCY_SCOPE_INCLUDES_DIRECT_DEPENDENCIES")
591591
public static let DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = BuiltinMacros.declareBooleanMacro("DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER")
592592
public static let __DIAGNOSE_DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER_ERROR = BuiltinMacros.declareBooleanMacro("__DIAGNOSE_DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER_ERROR")
@@ -2831,3 +2831,22 @@ extension BuildVersion.Platform {
28312831
return dtsn
28322832
}
28332833
}
2834+
2835+
public enum DependenciesVerificationSetting: String, Equatable, Hashable, EnumerationMacroType {
2836+
public static let defaultValue = DependenciesVerificationSetting.notset
2837+
2838+
case notset = "NOT_SET"
2839+
case enabled = "YES"
2840+
case disabled = "NO"
2841+
2842+
func isEnabled(onNotSet: Bool) -> Bool {
2843+
return switch self {
2844+
case .notset:
2845+
onNotSet
2846+
case .enabled:
2847+
true
2848+
case .disabled:
2849+
false
2850+
}
2851+
}
2852+
}

Sources/SWBCore/Specs/CoreBuildSystem.xcspec

-5
Original file line numberDiff line numberDiff line change
@@ -4536,11 +4536,6 @@ When this setting is enabled:
45364536
Name = "DEPENDENCIES";
45374537
Type = StringList;
45384538
},
4539-
{
4540-
Name = "DEPENDENCIES_VERIFICATION";
4541-
Type = Boolean;
4542-
DefaultValue = YES;
4543-
},
45444539
);
45454540
},
45464541
)

Tests/SWBCoreTests/DependencySettingsTests.swift

+23-10
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,29 @@ import SWBMacro
2222

2323
@Test
2424
func emptyDependenciesValueDisablesVerification() throws {
25-
var table1 = MacroValueAssignmentTable(namespace: BuiltinMacros.namespace)
26-
table1.push(BuiltinMacros.DEPENDENCIES_VERIFICATION, literal: true)
27-
let scope1 = MacroEvaluationScope(table: table1)
28-
#expect(!DependencySettings(scope1).verification)
29-
30-
var table2 = MacroValueAssignmentTable(namespace: BuiltinMacros.namespace)
31-
table2.push(BuiltinMacros.DEPENDENCIES_VERIFICATION, literal: true)
32-
table2.push(BuiltinMacros.DEPENDENCIES, literal: ["Foo"])
33-
let scope2 = MacroEvaluationScope(table: table2)
34-
#expect(DependencySettings(scope2).verification)
25+
#expect(!settings().verification)
26+
#expect(settings(dependencies: ["Foo"]).verification)
27+
#expect(settings(verification: .enabled).verification)
28+
#expect(!settings(dependencies: ["Foo"], verification: .disabled).verification)
29+
}
30+
31+
@Test
32+
func dependenciesAreOrderedAndUnique() throws {
33+
#expect(Array(settings(dependencies: ["B", "A", "B", "A"]).dependencies) == ["A", "B"])
34+
}
35+
36+
func settings(dependencies: [String]? = nil, verification: DependenciesVerificationSetting? = nil) -> DependencySettings {
37+
var table = MacroValueAssignmentTable(namespace: BuiltinMacros.namespace)
38+
if let verification {
39+
table.push(BuiltinMacros.DEPENDENCIES_VERIFICATION, literal: verification)
40+
}
41+
if let dependencies {
42+
table.push(BuiltinMacros.DEPENDENCIES, literal: dependencies)
43+
}
44+
45+
let scope = MacroEvaluationScope(table: table)
46+
return DependencySettings(scope)
47+
3548
}
3649

3750
}

Tests/SWBTaskConstructionTests/DependencyVerificationTaskConstructionTests.swift

+21-7
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fileprivate struct DependencyVerificationTaskConstructionTests: CoreBasedTests {
3131

3232
@Test
3333
func addsTraceArgsWhenDependenciesDeclared() async throws {
34-
try await testWith(dependencies: ["Foo"]) { tester, srcroot in
34+
try await testWith(["DEPENDENCIES": "Foo"]) { tester, srcroot in
3535
await tester.checkBuild(runDestination: .macOS) { results in
3636
results.checkTask(.matchRuleType("Ld")) { task in
3737
task.checkCommandLineContains([
@@ -44,7 +44,7 @@ fileprivate struct DependencyVerificationTaskConstructionTests: CoreBasedTests {
4444
"-Xclang", "-header-include-file",
4545
"-Xclang", outputFile(srcroot, "\(sourceBaseName).o.trace.json"),
4646
"-Xclang", "-header-include-filtering=only-direct-system",
47-
"-Xclang", "-header-include-format=json"
47+
"-Xclang", "-header-include-format=json",
4848
])
4949
}
5050
}
@@ -53,7 +53,7 @@ fileprivate struct DependencyVerificationTaskConstructionTests: CoreBasedTests {
5353

5454
@Test
5555
func noTraceArgsWhenDependenciesDeclared() async throws {
56-
try await testWith(dependencies: []) { tester, srcroot in
56+
try await testWith([:]) { tester, srcroot in
5757
await tester.checkBuild(runDestination: .macOS) { results in
5858
results.checkTask(.matchRuleType("Ld")) { task in
5959
task.checkCommandLineDoesNotContain("-trace_file")
@@ -65,7 +65,21 @@ fileprivate struct DependencyVerificationTaskConstructionTests: CoreBasedTests {
6565
}
6666
}
6767

68-
private func testWith(dependencies: [String], _ assertions: (_ tester: TaskConstructionTester, _ srcroot: Path) async throws -> Void) async throws {
68+
@Test
69+
func canEnableVerificationOfNoDependencies() async throws {
70+
try await testWith(["DEPENDENCIES_VERIFICATION": "YES"]) { tester, srcroot in
71+
await tester.checkBuild(runDestination: .macOS) { results in
72+
results.checkTask(.matchRuleType("Ld")) { task in
73+
task.checkCommandLineContains(["-Xlinker", "-trace_file",])
74+
}
75+
}
76+
}
77+
}
78+
79+
private func testWith(
80+
_ buildSettings: [String: String],
81+
_ assertions: (_ tester: TaskConstructionTester, _ srcroot: Path) async throws -> Void
82+
) async throws {
6983
let testProject = TestProject(
7084
project,
7185
groupTree: TestGroup(
@@ -77,11 +91,11 @@ fileprivate struct DependencyVerificationTaskConstructionTests: CoreBasedTests {
7791
TestBuildConfiguration(
7892
"Debug",
7993
buildSettings: [
80-
"DEPENDENCIES": dependencies.joined(separator: " "),
8194
"PRODUCT_NAME": "$(TARGET_NAME)",
8295
"GENERATE_INFOPLIST_FILE": "YES",
83-
"CLANG_ENABLE_MODULES": "YES"
84-
])
96+
"CLANG_ENABLE_MODULES": "YES",
97+
].merging(buildSettings) { _, new in new }
98+
)
8599
],
86100
targets: [
87101
TestStandardTarget(

0 commit comments

Comments
 (0)