From 1c1e0ecdf6fbaa64c14e858276093f5bddb02332 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 9 Jul 2026 15:51:31 -0400 Subject: [PATCH 1/8] Bootstrap a testing harness target. This PR adds a (stub, unimplemented, incomplete, _etc._) harness executable target that uses Swift Argument Parser. This target will eventually act as a host for tests, but for now just throws an error if invoked. --- Package.swift | 35 ++++++++++++++++----- Sources/CMakeLists.txt | 1 + Sources/Harness/CMakeLists.txt | 22 +++++++++++++ Sources/Harness/Harness.swift | 25 +++++++++++++++ cmake/modules/shared/CompilerSettings.cmake | 5 +++ 5 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 Sources/Harness/CMakeLists.txt create mode 100644 Sources/Harness/Harness.swift diff --git a/Package.swift b/Package.swift index dff2b7409..7bc0b7b56 100644 --- a/Package.swift +++ b/Package.swift @@ -68,29 +68,33 @@ let package = Package( 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 @@ -116,6 +120,9 @@ 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"), + + // TODO: determine the best version range to depend on here + .package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMajor(from: "1.8.0")), ], targets: [ @@ -289,6 +296,19 @@ 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", + exclude: ["CMakeLists.txt"], + swiftSettings: .packageSettings() + ), + // Utility targets: These are utilities intended for use when developing // this package, not for distribution. .executableTarget( @@ -510,6 +530,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), diff --git a/Sources/CMakeLists.txt b/Sources/CMakeLists.txt index 4fc0847b7..87bbcdf11 100644 --- a/Sources/CMakeLists.txt +++ b/Sources/CMakeLists.txt @@ -107,4 +107,5 @@ add_subdirectory(_TestDiscovery) add_subdirectory(_TestingInterop) add_subdirectory(_TestingInternals) add_subdirectory(Overlays) +add_subdirectory(Harness) add_subdirectory(Testing) diff --git a/Sources/Harness/CMakeLists.txt b/Sources/Harness/CMakeLists.txt new file mode 100644 index 000000000..c15eb41cf --- /dev/null +++ b/Sources/Harness/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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 + +if(NOT (CMAKE_SYSTEM_NAME IN_LIST SWT_NO_HARNESS_LIST)) + include(ModuleABIName) + + find_package(ArgumentParser CONFIG REQUIRED) + + add_executable(swift-testing-harness + Harness.swift) + target_link_libraries(swift-test PRIVATE + ArgumentParser + Testing) + + install(TARGETS swift-testing-harness + RUNTIME DESTINATION "libexec/swift/pm") +endif() diff --git a/Sources/Harness/Harness.swift b/Sources/Harness/Harness.swift new file mode 100644 index 000000000..c3f019f45 --- /dev/null +++ b/Sources/Harness/Harness.swift @@ -0,0 +1,25 @@ +// +// 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 +// + +#if !SWT_NO_HARNESS +@_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.") + } +} +#endif diff --git a/cmake/modules/shared/CompilerSettings.cmake b/cmake/modules/shared/CompilerSettings.cmake index 480e45f18..2ec58f8d4 100644 --- a/cmake/modules/shared/CompilerSettings.cmake +++ b/cmake/modules/shared/CompilerSettings.cmake @@ -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() From 39fd7983fe7305f9daa4036643fa5ade0171a029 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 9 Jul 2026 16:05:27 -0400 Subject: [PATCH 2/8] Nominally build the package target for unsupported platforms (but not CMake) --- Sources/Harness/Harness.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Sources/Harness/Harness.swift b/Sources/Harness/Harness.swift index c3f019f45..a1d3e3dd4 100644 --- a/Sources/Harness/Harness.swift +++ b/Sources/Harness/Harness.swift @@ -8,7 +8,6 @@ // See https://swift.org/CONTRIBUTORS.txt for Swift project authors // -#if !SWT_NO_HARNESS @_spi(ForToolsIntegrationOnly) private import Testing private import ArgumentParser @@ -22,4 +21,3 @@ private import ArgumentParser throw ValidationError("This tool is currently unimplemented.") } } -#endif From 88568b9d464084e81a0cc809e11ca3d8941f964d Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 9 Jul 2026 17:01:07 -0400 Subject: [PATCH 3/8] Fix typo --- Sources/Harness/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Harness/CMakeLists.txt b/Sources/Harness/CMakeLists.txt index c15eb41cf..2fb4492bb 100644 --- a/Sources/Harness/CMakeLists.txt +++ b/Sources/Harness/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT (CMAKE_SYSTEM_NAME IN_LIST SWT_NO_HARNESS_LIST)) add_executable(swift-testing-harness Harness.swift) - target_link_libraries(swift-test PRIVATE + target_link_libraries(swift-testing-harness PRIVATE ArgumentParser Testing) From ed880e2685ca5fd22dbdbfabf05490f92c776ff9 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 10 Jul 2026 10:24:45 -0400 Subject: [PATCH 4/8] Fetch ArgumentParser if the package is not found by CMake (is this completely correct? do we need to bootstrap something?) --- Package.swift | 7 +++++-- Sources/Harness/CMakeLists.txt | 11 +++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Package.swift b/Package.swift index 7bc0b7b56..83a9109e7 100644 --- a/Package.swift +++ b/Package.swift @@ -121,8 +121,11 @@ let package = Package( // always be used. .package(url: "https://github.com/swiftlang/swift-syntax.git", from: "604.0.0-latest"), - // TODO: determine the best version range to depend on here - .package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMajor(from: "1.8.0")), + // 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")), ], targets: [ diff --git a/Sources/Harness/CMakeLists.txt b/Sources/Harness/CMakeLists.txt index 2fb4492bb..cfb39eeba 100644 --- a/Sources/Harness/CMakeLists.txt +++ b/Sources/Harness/CMakeLists.txt @@ -9,7 +9,14 @@ if(NOT (CMAKE_SYSTEM_NAME IN_LIST SWT_NO_HARNESS_LIST)) include(ModuleABIName) - find_package(ArgumentParser CONFIG REQUIRED) + find_package(ArgumentParser CONFIG) + if(NOT ArgumentParser_FOUND) + message("-- Vending swift-argument-parser") + FetchContent_Declare(ArgumentParser + GIT_REPOSITORY https://github.com/apple/swift-argument-parser + GIT_TAG 1.5.1) + FetchContent_MakeAvailable(ArgumentParser) + endif() add_executable(swift-testing-harness Harness.swift) @@ -18,5 +25,5 @@ if(NOT (CMAKE_SYSTEM_NAME IN_LIST SWT_NO_HARNESS_LIST)) Testing) install(TARGETS swift-testing-harness - RUNTIME DESTINATION "libexec/swift/pm") + RUNTIME DESTINATION "libexec/swift/testing") endif() From 22a623098003f4d978c2237ba0e72227eba16cf0 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 10 Jul 2026 11:01:33 -0400 Subject: [PATCH 5/8] Explicitly include FetchContent module --- Sources/Harness/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/Harness/CMakeLists.txt b/Sources/Harness/CMakeLists.txt index cfb39eeba..2d9699a6d 100644 --- a/Sources/Harness/CMakeLists.txt +++ b/Sources/Harness/CMakeLists.txt @@ -7,6 +7,7 @@ # See https://swift.org/CONTRIBUTORS.txt for Swift project authors if(NOT (CMAKE_SYSTEM_NAME IN_LIST SWT_NO_HARNESS_LIST)) + include(FetchContent) include(ModuleABIName) find_package(ArgumentParser CONFIG) From 932b2aeb8b6d70097bf0f146740d5af8862dc4d4 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 10 Jul 2026 12:57:09 -0400 Subject: [PATCH 6/8] FetchContent fails in CI, okay then --- Sources/Harness/CMakeLists.txt | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Sources/Harness/CMakeLists.txt b/Sources/Harness/CMakeLists.txt index 2d9699a6d..9ab0606f8 100644 --- a/Sources/Harness/CMakeLists.txt +++ b/Sources/Harness/CMakeLists.txt @@ -7,17 +7,9 @@ # See https://swift.org/CONTRIBUTORS.txt for Swift project authors if(NOT (CMAKE_SYSTEM_NAME IN_LIST SWT_NO_HARNESS_LIST)) - include(FetchContent) include(ModuleABIName) - find_package(ArgumentParser CONFIG) - if(NOT ArgumentParser_FOUND) - message("-- Vending swift-argument-parser") - FetchContent_Declare(ArgumentParser - GIT_REPOSITORY https://github.com/apple/swift-argument-parser - GIT_TAG 1.5.1) - FetchContent_MakeAvailable(ArgumentParser) - endif() + find_package(ArgumentParser CONFIG REQUIRED) add_executable(swift-testing-harness Harness.swift) From 2fd68a9d0f531b3bc3f0f266431f21e510d76899 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 10 Jul 2026 14:50:02 -0400 Subject: [PATCH 7/8] Don't build with CMake, we'll build as a package instead after SwiftPM --- Package.swift | 10 ++++++++-- Sources/CMakeLists.txt | 1 - Sources/Harness/CMakeLists.txt | 22 ---------------------- 3 files changed, 8 insertions(+), 25 deletions(-) delete mode 100644 Sources/Harness/CMakeLists.txt diff --git a/Package.swift b/Package.swift index 83a9109e7..ae55af20e 100644 --- a/Package.swift +++ b/Package.swift @@ -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` @@ -110,7 +114,10 @@ let package = Package( return result }(), - dependencies: [ + dependencies: useLocalDependencies ? [ + .package(path: "../swift-syntax"), + .package(path: "../swift-argument-parser"), + ] : [ // 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 @@ -308,7 +315,6 @@ let package = Package( .product(name: "ArgumentParser", package: "swift-argument-parser"), ], path: "Sources/Harness", - exclude: ["CMakeLists.txt"], swiftSettings: .packageSettings() ), diff --git a/Sources/CMakeLists.txt b/Sources/CMakeLists.txt index 87bbcdf11..4fc0847b7 100644 --- a/Sources/CMakeLists.txt +++ b/Sources/CMakeLists.txt @@ -107,5 +107,4 @@ add_subdirectory(_TestDiscovery) add_subdirectory(_TestingInterop) add_subdirectory(_TestingInternals) add_subdirectory(Overlays) -add_subdirectory(Harness) add_subdirectory(Testing) diff --git a/Sources/Harness/CMakeLists.txt b/Sources/Harness/CMakeLists.txt deleted file mode 100644 index 9ab0606f8..000000000 --- a/Sources/Harness/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# 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 - -if(NOT (CMAKE_SYSTEM_NAME IN_LIST SWT_NO_HARNESS_LIST)) - include(ModuleABIName) - - find_package(ArgumentParser CONFIG REQUIRED) - - add_executable(swift-testing-harness - Harness.swift) - target_link_libraries(swift-testing-harness PRIVATE - ArgumentParser - Testing) - - install(TARGETS swift-testing-harness - RUNTIME DESTINATION "libexec/swift/testing") -endif() From 601a828af2538052aa6cca0b8eff2be95a1d0fea Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 10 Jul 2026 14:54:46 -0400 Subject: [PATCH 8/8] Put common case first in ternary operation in Package.swift --- Package.swift | 51 ++++++++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/Package.swift b/Package.swift index ae55af20e..c8dcfec7d 100644 --- a/Package.swift +++ b/Package.swift @@ -43,31 +43,24 @@ 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]() @@ -114,10 +107,7 @@ let package = Package( return result }(), - dependencies: useLocalDependencies ? [ - .package(path: "../swift-syntax"), - .package(path: "../swift-argument-parser"), - ] : [ + 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 @@ -133,6 +123,9 @@ let package = Package( // 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: [