@@ -33,19 +33,21 @@ extension BuildPlan {
33
33
_ observabilityScope: ObservabilityScope
34
34
) throws -> [ ( product: ResolvedProduct , discoveryTargetBuildDescription: SwiftTargetBuildDescription ? , entryPointTargetBuildDescription: SwiftTargetBuildDescription ) ] {
35
35
guard buildParameters. testingParameters. testProductStyle. requiresAdditionalDerivedTestTargets,
36
- case . entryPointExecutable( let explicitlySpecifiedPath) =
36
+ case . entryPointExecutable( let explicitlyEnabledDiscovery , let explicitlySpecifiedPath) =
37
37
buildParameters. testingParameters. testProductStyle
38
38
else {
39
39
throw InternalError ( " makeTestManifestTargets should not be used for build plan which does not require additional derived test targets " )
40
40
}
41
41
42
42
let isEntryPointPathSpecifiedExplicitly = explicitlySpecifiedPath != nil
43
43
44
+ var isDiscoveryEnabledRedundantly = explicitlyEnabledDiscovery && !isEntryPointPathSpecifiedExplicitly
44
45
var result : [ ( ResolvedProduct , SwiftTargetBuildDescription ? , SwiftTargetBuildDescription ) ] = [ ]
45
46
for testProduct in graph. allProducts where testProduct. type == . test {
46
47
guard let package = graph. package ( for: testProduct) else {
47
48
throw InternalError ( " package not found for \( testProduct) " )
48
49
}
50
+ isDiscoveryEnabledRedundantly = isDiscoveryEnabledRedundantly && nil == testProduct. testEntryPointTarget
49
51
// If a non-explicitly specified test entry point file exists, prefer that over test discovery.
50
52
// This is designed as an escape hatch when test discovery is not appropriate and for backwards
51
53
// compatibility for projects that have existing test entry point files (e.g. XCTMain.swift, LinuxMain.swift).
@@ -56,7 +58,10 @@ extension BuildPlan {
56
58
// `--experimental-test-entry-point-path <file>`. The latter is useful because it still performs test discovery and places the discovered
57
59
// tests into a separate target/module named "<PackageName>PackageDiscoveredTests". Then, that entry point file may import that module and
58
60
// obtain that list to pass it to the `XCTMain(...)` function and avoid needing to maintain a list of tests itself.
59
- if testProduct. testEntryPointTarget == nil , let testEntryPointPath = explicitlySpecifiedPath, !fileSystem. exists ( testEntryPointPath) {
61
+ if testProduct. testEntryPointTarget != nil && explicitlyEnabledDiscovery && !isEntryPointPathSpecifiedExplicitly {
62
+ let testEntryPointName = testProduct. underlying. testEntryPointPath? . basename ?? SwiftTarget . defaultTestEntryPointName
63
+ observabilityScope. emit ( warning: " '--enable-test-discovery' was specified so the ' \( testEntryPointName) ' entry point file for ' \( testProduct. name) ' will be ignored and an entry point will be generated automatically. To use test discovery with a custom entry point file, pass '--experimental-test-entry-point-path <file>'. " )
64
+ } else if testProduct. testEntryPointTarget == nil , let testEntryPointPath = explicitlySpecifiedPath, !fileSystem. exists ( testEntryPointPath) {
60
65
observabilityScope. emit ( error: " '--experimental-test-entry-point-path' was specified but the file ' \( testEntryPointPath) ' could not be found. " )
61
66
}
62
67
@@ -155,34 +160,43 @@ extension BuildPlan {
155
160
}
156
161
157
162
if let entryPointResolvedTarget = testProduct. testEntryPointTarget {
158
- if isEntryPointPathSpecifiedExplicitly {
159
- // Allow using the explicitly-specified test entry point target, but still perform test discovery and thus declare a dependency on the discovery targets.
160
- let entryPointTarget = SwiftTarget (
161
- name: entryPointResolvedTarget. underlying. name,
162
- dependencies: entryPointResolvedTarget. underlying. dependencies + swiftTargetDependencies,
163
- packageAccess: entryPointResolvedTarget. packageAccess,
164
- testEntryPointSources: entryPointResolvedTarget. underlying. sources
165
- )
166
- let entryPointResolvedTarget = ResolvedTarget (
167
- packageIdentity: testProduct. packageIdentity,
168
- underlying: entryPointTarget,
169
- dependencies: entryPointResolvedTarget. dependencies + resolvedTargetDependencies,
170
- defaultLocalization: testProduct. defaultLocalization,
171
- supportedPlatforms: testProduct. supportedPlatforms,
172
- platformVersionProvider: testProduct. platformVersionProvider
173
- )
174
- let entryPointTargetBuildDescription = try SwiftTargetBuildDescription (
175
- package : package ,
176
- target: entryPointResolvedTarget,
177
- toolsVersion: toolsVersion,
178
- buildParameters: buildParameters,
179
- testTargetRole: . entryPoint( isSynthesized: false ) ,
180
- disableSandbox: disableSandbox,
181
- fileSystem: fileSystem,
182
- observabilityScope: observabilityScope
183
- )
184
-
185
- result. append ( ( testProduct, discoveryTargets? . buildDescription, entryPointTargetBuildDescription) )
163
+ if isEntryPointPathSpecifiedExplicitly || explicitlyEnabledDiscovery {
164
+ if isEntryPointPathSpecifiedExplicitly {
165
+ // Allow using the explicitly-specified test entry point target, but still perform test discovery and thus declare a dependency on the discovery targets.
166
+ let entryPointTarget = SwiftTarget (
167
+ name: entryPointResolvedTarget. underlying. name,
168
+ dependencies: entryPointResolvedTarget. underlying. dependencies + swiftTargetDependencies,
169
+ packageAccess: entryPointResolvedTarget. packageAccess,
170
+ testEntryPointSources: entryPointResolvedTarget. underlying. sources
171
+ )
172
+ let entryPointResolvedTarget = ResolvedTarget (
173
+ packageIdentity: testProduct. packageIdentity,
174
+ underlying: entryPointTarget,
175
+ dependencies: entryPointResolvedTarget. dependencies + resolvedTargetDependencies,
176
+ defaultLocalization: testProduct. defaultLocalization,
177
+ supportedPlatforms: testProduct. supportedPlatforms,
178
+ platformVersionProvider: testProduct. platformVersionProvider
179
+ )
180
+ let entryPointTargetBuildDescription = try SwiftTargetBuildDescription (
181
+ package : package ,
182
+ target: entryPointResolvedTarget,
183
+ toolsVersion: toolsVersion,
184
+ buildParameters: buildParameters,
185
+ testTargetRole: . entryPoint( isSynthesized: false ) ,
186
+ disableSandbox: disableSandbox,
187
+ fileSystem: fileSystem,
188
+ observabilityScope: observabilityScope
189
+ )
190
+
191
+ result. append ( ( testProduct, discoveryTargets? . buildDescription, entryPointTargetBuildDescription) )
192
+ } else {
193
+ // Ignore test entry point and synthesize one, declaring a dependency on the test discovery targets created above.
194
+ let entryPointTargetBuildDescription = try generateSynthesizedEntryPointTarget (
195
+ swiftTargetDependencies: swiftTargetDependencies,
196
+ resolvedTargetDependencies: resolvedTargetDependencies
197
+ )
198
+ result. append ( ( testProduct, discoveryTargets? . buildDescription, entryPointTargetBuildDescription) )
199
+ }
186
200
} else {
187
201
// Use the test entry point as-is, without performing test discovery.
188
202
let entryPointTargetBuildDescription = try SwiftTargetBuildDescription (
@@ -207,6 +221,10 @@ extension BuildPlan {
207
221
}
208
222
}
209
223
224
+ if isDiscoveryEnabledRedundantly {
225
+ observabilityScope. emit ( warning: " '--enable-test-discovery' option is deprecated; tests are automatically discovered on all platforms " )
226
+ }
227
+
210
228
return result
211
229
}
212
230
}
0 commit comments