@@ -128,6 +128,9 @@ public struct BuildParameters {
128
128
/// Whether to enable code coverage.
129
129
public let enableCodeCoverage : Bool
130
130
131
+ /// Whether to enable test discovery on platforms without Objective-C runtime.
132
+ public let enableTestDiscovery : Bool
133
+
131
134
/// Whether to enable generation of `.swiftinterface` files alongside
132
135
/// `.swiftmodule`s.
133
136
public let enableParseableModuleInterfaces : Bool
@@ -156,7 +159,8 @@ public struct BuildParameters {
156
159
sanitizers: EnabledSanitizers = EnabledSanitizers ( ) ,
157
160
enableCodeCoverage: Bool = false ,
158
161
indexStoreMode: IndexStoreMode = . auto,
159
- enableParseableModuleInterfaces: Bool = false
162
+ enableParseableModuleInterfaces: Bool = false ,
163
+ enableTestDiscovery: Bool = false
160
164
) {
161
165
self . dataPath = dataPath
162
166
self . configuration = configuration
@@ -170,6 +174,7 @@ public struct BuildParameters {
170
174
self . enableCodeCoverage = enableCodeCoverage
171
175
self . indexStoreMode = indexStoreMode
172
176
self . enableParseableModuleInterfaces = enableParseableModuleInterfaces
177
+ self . enableTestDiscovery = enableTestDiscovery
173
178
}
174
179
175
180
/// Returns the compiler arguments for the index store, if enabled.
@@ -445,6 +450,7 @@ public final class SwiftTargetBuildDescription {
445
450
446
451
/// The objects in this target.
447
452
var objects : [ AbsolutePath ] {
453
+ // Otherwise, use sources from the target.
448
454
return target. sources. relativePaths. map ( { tempsPath. appending ( RelativePath ( " \( $0. pathString) .o " ) ) } )
449
455
}
450
456
@@ -469,13 +475,22 @@ public final class SwiftTargetBuildDescription {
469
475
/// If this target is a test target.
470
476
public let isTestTarget : Bool
471
477
478
+ /// True if this is the test discovery target.
479
+ public let testDiscoveryTarget : Bool
480
+
472
481
/// Create a new target description with target and build parameters.
473
- init ( target: ResolvedTarget , buildParameters: BuildParameters , isTestTarget: Bool ? = nil ) {
482
+ init (
483
+ target: ResolvedTarget ,
484
+ buildParameters: BuildParameters ,
485
+ isTestTarget: Bool ? = nil ,
486
+ testDiscoveryTarget: Bool = false
487
+ ) {
474
488
assert ( target. underlyingTarget is SwiftTarget , " underlying target type mismatch \( target) " )
475
489
self . target = target
476
490
self . buildParameters = buildParameters
477
491
// Unless mentioned explicitly, use the target type to determine if this is a test target.
478
492
self . isTestTarget = isTestTarget ?? ( target. type == . test)
493
+ self . testDiscoveryTarget = testDiscoveryTarget
479
494
}
480
495
481
496
/// The arguments needed to compile this target.
@@ -868,6 +883,65 @@ public class BuildPlan {
868
883
/// Diagnostics Engine for emitting diagnostics.
869
884
let diagnostics : DiagnosticsEngine
870
885
886
+ private static func planLinuxMain(
887
+ _ buildParameters: BuildParameters ,
888
+ _ graph: PackageGraph
889
+ ) throws -> ( ResolvedTarget , SwiftTargetBuildDescription ) ? {
890
+ guard buildParameters. triple. isLinux ( ) else {
891
+ return nil
892
+ }
893
+
894
+ // Currently, there can be only one test product in a package graph.
895
+ guard let testProduct = graph. allProducts. first ( where: { $0. type == . test } ) else {
896
+ return nil
897
+ }
898
+
899
+ if !buildParameters. enableTestDiscovery {
900
+ guard let linuxMainTarget = testProduct. linuxMainTarget else {
901
+ throw Error . missingLinuxMain
902
+ }
903
+
904
+ let desc = SwiftTargetBuildDescription (
905
+ target: linuxMainTarget,
906
+ buildParameters: buildParameters,
907
+ isTestTarget: true
908
+ )
909
+ return ( linuxMainTarget, desc)
910
+ }
911
+
912
+ // We'll generate sources containing the test names as part of the build process.
913
+ let derivedTestListDir = buildParameters. buildPath. appending ( components: " testlist.derived " )
914
+ let mainFile = derivedTestListDir. appending ( component: " main.swift " )
915
+
916
+ var paths : [ AbsolutePath ] = [ ]
917
+ paths. append ( mainFile)
918
+ let testTargets = graph. rootPackages. flatMap { $0. targets } . filter { $0. type == . test }
919
+ for testTarget in testTargets {
920
+ let path = derivedTestListDir. appending ( components: testTarget. name + " .swift " )
921
+ paths. append ( path)
922
+ }
923
+
924
+ let src = Sources ( paths: paths, root: derivedTestListDir)
925
+
926
+ let swiftTarget = SwiftTarget (
927
+ testDiscoverySrc: src,
928
+ name: testProduct. name,
929
+ dependencies: testProduct. underlyingProduct. targets)
930
+ let linuxMainTarget = ResolvedTarget (
931
+ target: swiftTarget,
932
+ dependencies: testProduct. targets. map ( ResolvedTarget . Dependency. target)
933
+ )
934
+
935
+ let target = SwiftTargetBuildDescription (
936
+ target: linuxMainTarget,
937
+ buildParameters: buildParameters,
938
+ isTestTarget: true ,
939
+ testDiscoveryTarget: true
940
+ )
941
+
942
+ return ( linuxMainTarget, target)
943
+ }
944
+
871
945
/// Create a build plan with build parameters and a package graph.
872
946
public init (
873
947
buildParameters: BuildParameters ,
@@ -921,19 +995,10 @@ public class BuildPlan {
921
995
throw Diagnostics . fatalError
922
996
}
923
997
924
- if buildParameters. triple. isLinux ( ) {
925
- // FIXME: Create a target for LinuxMain file on linux.
926
- // This will go away once it is possible to auto detect tests.
927
- let testProducts = graph. allProducts. filter ( { $0. type == . test } )
928
-
929
- for product in testProducts {
930
- guard let linuxMainTarget = product. linuxMainTarget else {
931
- throw Error . missingLinuxMain
932
- }
933
- let target = SwiftTargetBuildDescription (
934
- target: linuxMainTarget, buildParameters: buildParameters, isTestTarget: true )
935
- targetMap [ linuxMainTarget] = . swift( target)
936
- }
998
+ // Plan the linux main target.
999
+ if let result = try Self . planLinuxMain ( buildParameters, graph) {
1000
+ targetMap [ result. 0 ] = . swift( result. 1 )
1001
+ self . linuxMainTarget = result. 0
937
1002
}
938
1003
939
1004
var productMap : [ ResolvedProduct : ProductBuildDescription ] = [ : ]
@@ -953,6 +1018,8 @@ public class BuildPlan {
953
1018
try plan ( )
954
1019
}
955
1020
1021
+ private var linuxMainTarget : ResolvedTarget ?
1022
+
956
1023
static func validateDeploymentVersionOfProductDependency(
957
1024
_ product: ResolvedProduct ,
958
1025
forTarget target: ResolvedTarget ,
@@ -1094,7 +1161,7 @@ public class BuildPlan {
1094
1161
1095
1162
if buildParameters. triple. isLinux ( ) {
1096
1163
if product. type == . test {
1097
- product . linuxMainTarget. map ( { staticTargets. append ( $0) } )
1164
+ linuxMainTarget. map ( { staticTargets. append ( $0) } )
1098
1165
}
1099
1166
}
1100
1167
0 commit comments