Skip to content

Commit 2778033

Browse files
committed
Skip build of test runners on darwin platforms
1 parent e32a104 commit 2778033

File tree

5 files changed

+109
-6
lines changed

5 files changed

+109
-6
lines changed

Sources/SWBApplePlatform/Specs/DarwinProductTypes.xcspec

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,17 @@
461461
);
462462
Platforms = (driverkit);
463463
},
464+
{
465+
_Domain = darwin;
466+
Type = ProductType;
467+
Identifier = com.apple.product-type.tool.swiftpm-test-runner;
468+
Name = "SwiftPM Unit Test Runner";
469+
Description = "SwiftPM Unit Test Runner";
470+
DefaultBuildProperties = {
471+
__SKIP_BUILD = YES;
472+
};
473+
PackageTypes = (
474+
com.apple.package-type.mach-o-executable
475+
);
476+
},
464477
)

Sources/SWBCore/Settings/BuiltinMacros.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,8 @@ public final class BuiltinMacros {
13011301
// Info.plist Keys - Sticker Packs
13021302
public static let INFOPLIST_KEY_NSStickerSharingLevel = BuiltinMacros.declareEnumMacro("INFOPLIST_KEY_NSStickerSharingLevel") as EnumMacroDeclaration<StickerSharingLevel>
13031303

1304+
public static let __SKIP_BUILD = BuiltinMacros.declareBooleanMacro("__SKIP_BUILD")
1305+
13041306
// MARK: Built-in Macro Initialization
13051307

13061308
private static var initialized = false
@@ -2393,7 +2395,8 @@ public final class BuiltinMacros {
23932395
ENABLE_XOJIT_PREVIEWS,
23942396
BUILD_ACTIVE_RESOURCES_ONLY,
23952397
ENABLE_ONLY_ACTIVE_RESOURCES,
2396-
ENABLE_PLAYGROUND_RESULTS
2398+
ENABLE_PLAYGROUND_RESULTS,
2399+
__SKIP_BUILD
23972400
]
23982401

23992402
/// Force initialization of entitlements macros.

Sources/SWBCore/TargetDependencyResolver.swift

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -553,18 +553,24 @@ fileprivate extension TargetDependencyResolver {
553553
delegate.emit(.init(behavior: .error, location: .unknown, data: .init("The 'Skip Dependencies' option is deprecated and can no longer be used.")))
554554
}
555555

556-
// Apply the requested dependency scope to the graph.
556+
// Prune targets from the graph as needed.
557+
var keptTargets: OrderedSet<ConfiguredTarget>
558+
var removedTargets: OrderedSet<ConfiguredTarget>
559+
560+
// First, determine targets to be removed based on the dependency scope.
557561
switch buildRequest.dependencyScope {
558562
case .workspace:
559563
// If dependencies are scoped to the workspace, no pruning is required.
564+
keptTargets = allTargets
565+
removedTargets = []
560566
break
561567
case .buildRequest:
562568
if buildRequest.skipDependencies {
563569
delegate.emit(.init(behavior: .error, location: .unknown, data: .init("The 'Skip Dependencies' option is deprecated and cannot be combined with dependency scopes.")))
564570
}
565571
// First, partition the targets into those we're keeping, and those we're removing.
566-
var keptTargets: OrderedSet<ConfiguredTarget> = []
567-
var removedTargets: OrderedSet<ConfiguredTarget> = []
572+
keptTargets = []
573+
removedTargets = []
568574
let requestedTargetGUIDs = Set(buildRequest.buildTargets.map(\.target.guid))
569575
var extraRequestedTargetGUIDs: Set<String> = []
570576
var potentialExtraRequestedPackageTargetGUIDs: Set<String> = []
@@ -594,8 +600,18 @@ fileprivate extension TargetDependencyResolver {
594600
removedTargets.append(configuredTarget)
595601
}
596602
}
603+
}
604+
605+
// Then, remove targets based on the value of the __SKIP_BUILD setting.
606+
let targetsToRemoveBasedOnSettings = keptTargets.filter { configuredTarget in
607+
let settings = buildRequestContext.getCachedSettings(configuredTarget.parameters, target: configuredTarget.target)
608+
return settings.globalScope.evaluate(BuiltinMacros.__SKIP_BUILD)
609+
}
610+
keptTargets.subtract(targetsToRemoveBasedOnSettings)
611+
removedTargets.append(contentsOf: targetsToRemoveBasedOnSettings)
597612

598-
// For each removed target, identify all kept targets reachable by traversing only edges which originate at a removed target.
613+
// For each removed target, identify all kept targets reachable by traversing only edges which originate at a removed target.
614+
if !removedTargets.isEmpty {
599615
var reachableKeptTargetsByRemovedTarget: [ConfiguredTarget: OrderedSet<ConfiguredTarget>] = [:]
600616
do {
601617
func visit(_ configuredTarget: ConfiguredTarget) {

Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/InfoPlistTaskProducer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ private extension ProductTypeSpec
5757
break
5858
}
5959

60-
fatalError("unknown product type")
60+
fatalError("unknown product type \(type(of: self))")
6161
}
6262
}
6363

Tests/SWBCoreTests/DependencyScopingTests.swift

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,77 @@ import Foundation
100100
}
101101
}
102102

103+
@Test(.requireSDKs(.macOS))
104+
func skipBuildSetting() async throws {
105+
let core = try await getCore()
106+
107+
let workspace = try TestWorkspace(
108+
"Workspace",
109+
projects: [
110+
TestProject(
111+
"P1",
112+
groupTree: TestGroup(
113+
"G1",
114+
children: [
115+
TestFile("S1.c"),
116+
]
117+
),
118+
buildConfigurations: [
119+
TestBuildConfiguration("Debug", buildSettings: [:]),
120+
],
121+
targets: [
122+
TestStandardTarget(
123+
"T1",
124+
type: .framework,
125+
buildConfigurations: [
126+
TestBuildConfiguration("Debug", buildSettings: ["PRODUCT_NAME": "$(TARGET_NAME)", "__SKIP_BUILD": "YES"]),
127+
],
128+
buildPhases: [
129+
TestSourcesBuildPhase(["S1.c"])
130+
],
131+
dependencies: ["T2"]
132+
),
133+
TestStandardTarget(
134+
"T2",
135+
type: .framework,
136+
buildConfigurations: [
137+
TestBuildConfiguration("Debug", buildSettings: ["PRODUCT_NAME": "$(TARGET_NAME)"]),
138+
],
139+
buildPhases: [
140+
TestSourcesBuildPhase(["S1.c"])
141+
],
142+
dependencies: ["T3"]
143+
),
144+
TestStandardTarget(
145+
"T3",
146+
type: .framework,
147+
buildConfigurations: [
148+
TestBuildConfiguration("Debug", buildSettings: ["PRODUCT_NAME": "$(TARGET_NAME)"]),
149+
],
150+
buildPhases: [
151+
TestSourcesBuildPhase(["S1.c"])
152+
]
153+
)
154+
]
155+
),
156+
]
157+
).load(core)
158+
let workspaceContext = WorkspaceContext(core: core, workspace: workspace, processExecutionCache: .sharedForTesting)
159+
160+
// Configure the targets and create a BuildRequest.
161+
let buildParameters = BuildParameters(configuration: "Debug")
162+
let t1 = BuildRequest.BuildTargetInfo(parameters: buildParameters, target: workspace.target(named: "T1")!)
163+
let t2 = BuildRequest.BuildTargetInfo(parameters: buildParameters, target: workspace.target(named: "T2")!)
164+
do {
165+
let buildRequest = BuildRequest(parameters: buildParameters, buildTargets: [t1], dependencyScope: .workspace, continueBuildingAfterErrors: true, useParallelTargets: false, useImplicitDependencies: true, useDryRun: false)
166+
let buildRequestContext = BuildRequestContext(workspaceContext: workspaceContext)
167+
let delegate = EmptyTargetDependencyResolverDelegate(workspace: workspaceContext.workspace)
168+
let buildGraph = await TargetGraphFactory(workspaceContext: workspaceContext, buildRequest: buildRequest, buildRequestContext: buildRequestContext, delegate: delegate).graph(type: .dependency)
169+
#expect(buildGraph.allTargets.map({ $0.target.name }) == ["T3", "T2"])
170+
delegate.checkNoDiagnostics()
171+
}
172+
}
173+
103174
@Test(.requireSDKs(.macOS))
104175
func buildRequestScopeRemovingInteriorTarget() async throws {
105176
let core = try await getCore()

0 commit comments

Comments
 (0)