diff --git a/Package.swift b/Package.swift index dff2b7409..c8dcfec7d 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` @@ -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 @@ -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 @@ -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: [ @@ -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( @@ -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), diff --git a/Sources/Harness/Harness.swift b/Sources/Harness/Harness.swift new file mode 100644 index 000000000..a1d3e3dd4 --- /dev/null +++ b/Sources/Harness/Harness.swift @@ -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.") + } +} 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()