Skip to content

Use a different path extension for swift-testing builds #7163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Sources/Build/BuildManifest/LLBuildManifestBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,9 @@ extension LLBuildManifestBuilder {

let outputs = testEntryPointTarget.target.sources.paths

guard let mainOutput = (outputs.first { $0.basename == TestEntryPointTool.mainFileName }) else {
throw InternalError("main output (\(TestEntryPointTool.mainFileName)) not found")
let mainFileName = TestEntryPointTool.mainFileName(for: buildParameters.testingParameters.library)
guard let mainOutput = (outputs.first { $0.basename == mainFileName }) else {
throw InternalError("main output (\(mainFileName)) not found")
}
let cmdName = mainOutput.pathString
self.manifest.addTestEntryPointCmd(
Expand Down
14 changes: 11 additions & 3 deletions Sources/Build/BuildOperationBuildSystemDelegateHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,22 @@ final class TestDiscoveryCommand: CustomLLBuildCommand, TestBuildCommand {
}
}

extension TestEntryPointTool {
public static func mainFileName(for library: BuildParameters.Testing.Library) -> String {
"runner-\(library).swift"
}
}

final class TestEntryPointCommand: CustomLLBuildCommand, TestBuildCommand {
private func execute(fileSystem: Basics.FileSystem, tool: TestEntryPointTool) throws {
let outputs = tool.outputs.compactMap { try? AbsolutePath(validating: $0.name) }

// Find the main output file
let mainFileName = TestEntryPointTool.mainFileName(for: self.context.buildParameters.testingParameters.library)
guard let mainFile = outputs.first(where: { path in
path.basename == TestEntryPointTool.mainFileName
path.basename == mainFileName
}) else {
throw InternalError("main file output (\(TestEntryPointTool.mainFileName)) not found")
throw InternalError("main file output (\(mainFileName)) not found")
}

// Write the main file.
Expand Down Expand Up @@ -393,7 +400,8 @@ public struct BuildDescription: Codable {
return try BuiltTestProduct(
productName: desc.product.name,
binaryPath: desc.binaryPath,
packagePath: desc.package.path
packagePath: desc.package.path,
library: desc.buildParameters.testingParameters.library
)
}
self.pluginDescriptions = pluginDescriptions
Expand Down
3 changes: 2 additions & 1 deletion Sources/Build/BuildPlan/BuildPlan+Test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ extension BuildPlan {
resolvedTargetDependencies: [ResolvedTarget.Dependency]
) throws -> SwiftTargetBuildDescription {
let entryPointDerivedDir = buildParameters.buildPath.appending(components: "\(testProduct.name).derived")
let entryPointMainFile = entryPointDerivedDir.appending(component: TestEntryPointTool.mainFileName)
let entryPointMainFileName = TestEntryPointTool.mainFileName(for: buildParameters.testingParameters.library)
let entryPointMainFile = entryPointDerivedDir.appending(component: entryPointMainFileName)
let entryPointSources = Sources(paths: [entryPointMainFile], root: entryPointDerivedDir)

let entryPointTarget = SwiftTarget(
Expand Down
1 change: 0 additions & 1 deletion Sources/LLBuildManifest/Tools.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ public struct TestDiscoveryTool: ToolProtocol {

public struct TestEntryPointTool: ToolProtocol {
public static let name: String = "test-entry-point-tool"
public static let mainFileName: String = "runner.swift"

public var inputs: [Node]
public var outputs: [Node]
Expand Down
16 changes: 10 additions & 6 deletions Sources/SPMBuildCore/BuildParameters/BuildParameters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,16 @@ public struct BuildParameters: Encodable {
guard !targetTriple.isWASI() else {
return try RelativePath(validating: "\(product.name).wasm")
}

let base = "\(product.name).xctest"
if targetTriple.isDarwin() {
return try RelativePath(validating: "\(base)/Contents/MacOS/\(product.name)")
} else {
return try RelativePath(validating: base)
switch testingParameters.library {
case .xctest:
let base = "\(product.name).xctest"
if targetTriple.isDarwin() {
return try RelativePath(validating: "\(base)/Contents/MacOS/\(product.name)")
} else {
return try RelativePath(validating: base)
}
case .swiftTesting:
return try RelativePath(validating: "\(product.name).swift-testing")
}
case .macro:
#if BUILD_MACROS_AS_DYLIBS
Expand Down
21 changes: 18 additions & 3 deletions Sources/SPMBuildCore/BuiltTestProduct.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,39 @@ public struct BuiltTestProduct: Codable {
public let packagePath: AbsolutePath

/// The path of the test bundle.
///
/// When the test product is not bundled (for instance, when using XCTest on
/// non-Darwin targets), this path is equal to ``binaryPath``.
public var bundlePath: AbsolutePath {
// Go up the folder hierarchy until we find the .xctest bundle.
// Go up the folder hierarchy until we find the .xctest or
// .swift-testing bundle.
let pathExtension: String
switch library {
case .xctest:
pathExtension = ".xctest"
case .swiftTesting:
pathExtension = ".swift-testing"
}
let hierarchySequence = sequence(first: binaryPath, next: { $0.isRoot ? nil : $0.parentDirectory })
guard let bundlePath = hierarchySequence.first(where: { $0.basename.hasSuffix(".xctest") }) else {
guard let bundlePath = hierarchySequence.first(where: { $0.basename.hasSuffix(pathExtension) }) else {
fatalError("could not find test bundle path from '\(binaryPath)'")
}

return bundlePath
}

/// The library used to build this test product.
public var library: BuildParameters.Testing.Library

/// Creates a new instance.
/// - Parameters:
/// - productName: The test product name.
/// - binaryPath: The path of the test binary.
/// - packagePath: The path to the package this product was declared in.
public init(productName: String, binaryPath: AbsolutePath, packagePath: AbsolutePath) {
public init(productName: String, binaryPath: AbsolutePath, packagePath: AbsolutePath, library: BuildParameters.Testing.Library) {
self.productName = productName
self.binaryPath = binaryPath
self.packagePath = packagePath
self.library = library
}
}
11 changes: 5 additions & 6 deletions Sources/SPMTestSupport/SwiftPMProduct.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,11 @@ extension SwiftPM {
}
}

/// Path to currently built binary.
public var path: AbsolutePath {
return Self.testBinaryPath(for: self.executableName)
public var xctestBinaryPath: AbsolutePath {
Self.xctestBinaryPath(for: executableName)
}

public static func testBinaryPath(for executableName: RelativePath) -> AbsolutePath {
public static func xctestBinaryPath(for executableName: RelativePath) -> AbsolutePath {
#if canImport(Darwin)
for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") {
return try! AbsolutePath(AbsolutePath(validating: bundle.bundlePath).parentDirectory, executableName)
Expand Down Expand Up @@ -114,15 +113,15 @@ extension SwiftPM {
#endif
// FIXME: We use this private environment variable hack to be able to
// create special conditions in swift-build for swiftpm tests.
environment["SWIFTPM_TESTS_MODULECACHE"] = self.path.parentDirectory.pathString
environment["SWIFTPM_TESTS_MODULECACHE"] = xctestBinaryPath.parentDirectory.pathString
#if !os(Windows)
environment["SDKROOT"] = nil
#endif

// Unset the internal env variable that allows skipping certain tests.
environment["_SWIFTPM_SKIP_TESTS_LIST"] = nil

var completeArgs = [self.path.pathString]
var completeArgs = [xctestBinaryPath.pathString]
if let packagePath = packagePath {
completeArgs += ["--package-path", packagePath.pathString]
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/XCBuildSupport/XcodeBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem {
BuiltTestProduct(
productName: product.name,
binaryPath: binaryPath,
packagePath: package.path
packagePath: package.path,
library: buildParameters.testingParameters.library
)
)
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/CommandsTests/BuildToolTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ final class BuildToolTests: CommandsTestCase {
return buildArenaPath.appending(component: filename)
}

let dummySwiftcPath = SwiftPM.testBinaryPath(for: "dummy-swiftc")
let dummySwiftcPath = SwiftPM.xctestBinaryPath(for: "dummy-swiftc")
let swiftCompilerPath = try UserToolchain.default.swiftCompilerPath

var environment = [
Expand Down
2 changes: 1 addition & 1 deletion Tests/CommandsTests/RunToolTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ final class RunToolTests: CommandsTestCase {
let sync = DispatchGroup()
let outputHandler = OutputHandler(sync: sync)
let process = Process(
arguments: [SwiftPM.Run.path.pathString, "--package-path", fixturePath.pathString],
arguments: [SwiftPM.Run.xctestBinaryPath.pathString, "--package-path", fixturePath.pathString],
outputRedirection: .stream(stdout: outputHandler.handle(bytes:), stderr: outputHandler.handle(bytes:))
)

Expand Down