Skip to content
89 changes: 56 additions & 33 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ let git = Context.gitInformation
/// distribution as a package dependency.
let buildingForDevelopment = (git?.currentTag == nil)

/// Whether or not to use package dependencies checked out next to the testing
/// library's package directory instead of downloading them on demand.
let useLocalDependencies = Context.environment["SWIFTCI_USE_LOCAL_DEPS"] != nil

/// Whether or not this package is being built for Embedded Swift.
///
/// This value is `true` if `SWT_EMBEDDED` is set in the environment to `true`
Expand All @@ -39,58 +43,55 @@ let buildingForEmbedded: Bool = {
let package = Package(
name: "swift-testing",

platforms: {
if !buildingForEmbedded {
[
.macOS(.v14),
.iOS(.v17),
.watchOS(.v10),
.tvOS(.v17),
.macCatalyst(.v17),
.visionOS(.v1),
]
} else {
// Open-source main-branch toolchains (currently required to build this
// package for Embedded Swift) have higher Apple platform deployment
// targets than we would otherwise require.
[
.macOS(.v14),
.iOS(.v18),
.watchOS(.v10),
.tvOS(.v18),
.macCatalyst(.v18),
.visionOS(.v1),
]
}
}(),

platforms: !buildingForEmbedded ? [
.macOS(.v14),
.iOS(.v17),
.watchOS(.v10),
.tvOS(.v17),
.macCatalyst(.v17),
.visionOS(.v1),
] : [
// Open-source main-branch toolchains (currently required to build this
// package for Embedded Swift) have higher Apple platform deployment
// targets than we would otherwise require.
.macOS(.v14),
.iOS(.v18),
.watchOS(.v10),
.tvOS(.v18),
.macCatalyst(.v18),
.visionOS(.v1),
],
products: {
var result = [Product]()

#if os(Windows)
result.append(
result += [
.library(
name: "Testing",
type: .dynamic, // needed so Windows exports ABI entry point symbols
targets: ["Testing"]
)
)
]
#else
result.append(
result += [
.library(
name: "Testing",
targets: ["Testing"]
)
)
]
#endif

result.append(
result += [
.library(
name: "_TestDiscovery",
type: .static,
targets: ["_TestDiscovery"]
)
)
),
.executable(
name: "swift-testing-harness",
targets: ["swift-testing-harness"]
),
]

#if DEBUG
// Build _TestingInterop for debugging/testing purposes only. It is
Expand All @@ -106,7 +107,7 @@ let package = Package(
return result
}(),

dependencies: [
dependencies: !useLocalDependencies ? [
// swift-syntax periodically publishes a new tag with a suffix of the format
// "-prerelease-YYYY-MM-DD". We always want to use the most recent tag
// associated with a particular Swift version, without needing to hardcode
Expand All @@ -116,6 +117,15 @@ let package = Package(
// specified semantic version, meaning the most recent "prerelease" tag will
// always be used.
.package(url: "https://github.com/swiftlang/swift-syntax.git", from: "604.0.0-latest"),

// Add a dependency on Swift Argument Parser. Note that the rest of the
// toolchain (as of this writing) uses 1.5.x, so we match that; if the
// toolchain updates its dependency, please update the version number here
// and in Sources/Harness/CMakeLists.txt.
.package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMajor(from: "1.5.0")),
] : [
.package(path: "../swift-syntax"),
.package(path: "../swift-argument-parser"),
],

targets: [
Expand Down Expand Up @@ -289,6 +299,18 @@ let package = Package(
swiftSettings: .packageSettings() + .enableLibraryEvolution() + .moduleABIName("_Testing_WinSDK")
),

// Testing harness: a process that runs in between a host like SwiftPM and
// the actual test process(es) and which manages interactions between them.
.executableTarget(
name: "swift-testing-harness",
dependencies: [
"Testing",
.product(name: "ArgumentParser", package: "swift-argument-parser"),
],
path: "Sources/Harness",
swiftSettings: .packageSettings()
),

// Utility targets: These are utilities intended for use when developing
// this package, not for distribution.
.executableTarget(
Expand Down Expand Up @@ -510,6 +532,7 @@ extension Array where Element: _LanguageBuildSetting {
"SWT_NO_ABI_JSON_SCHEMA": (platforms: .none, embedded: true),
"SWT_NO_CODABLE": (platforms: .none, embedded: true),
"SWT_NO_INTEROP": (platforms: .none, embedded: true),
"SWT_NO_HARNESS": (platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android], embedded: true),
"SWT_NO_UNSTRUCTURED_TASKS": (platforms: .none, embedded: true),
"SWT_NO_GLOBAL_ACTORS": (platforms: .none, embedded: true),
"SWT_NO_SUSPENDING_CLOCK": (platforms: .none, embedded: true),
Expand Down
23 changes: 23 additions & 0 deletions Sources/Harness/Harness.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2026 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
//

@_spi(ForToolsIntegrationOnly) private import Testing
private import ArgumentParser

/// The harness' main command (i.e. its entry point).
@main struct Harness: Sendable, AsyncParsableCommand {
fileprivate static let configuration = CommandConfiguration(
commandName: "swift-testing-harness"
)

mutating func run() async throws {
throw ValidationError("This tool is currently unimplemented.")
}
}
5 changes: 5 additions & 0 deletions cmake/modules/shared/CompilerSettings.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,8 @@ if((NOT BUILD_SHARED_LIBS) AND (NOT CMAKE_SYSTEM_NAME STREQUAL "WASI"))
# When building a static library, Interop is not supported at this time
add_compile_definitions("SWT_NO_INTEROP")
endif()

set(SWT_NO_HARNESS_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI" "Android")
if(CMAKE_SYSTEM_NAME IN_LIST SWT_NO_HARNESS_LIST)
add_compile_definitions("SWT_NO_HARNESS")
endif()
Loading