Skip to content
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

[6.0][PackageModel] UserToolchain: Add -F when building with CommandLineTools #8035

Merged
merged 2 commits into from
Oct 15, 2024
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
8 changes: 4 additions & 4 deletions Sources/Commands/PackageCommands/Init.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ extension SwiftPackageCommand {
// For macros this is reversed, since we don't support testing
// macros with Swift Testing yet.
var supportedTestingLibraries = Set<BuildParameters.Testing.Library>()
if testLibraryOptions.isExplicitlyEnabled(.xctest) ||
(initMode == .macro && testLibraryOptions.isEnabled(.xctest)) {
if testLibraryOptions.isExplicitlyEnabled(.xctest, swiftCommandState: swiftCommandState) ||
(initMode == .macro && testLibraryOptions.isEnabled(.xctest, swiftCommandState: swiftCommandState)) {
supportedTestingLibraries.insert(.xctest)
}
if testLibraryOptions.isExplicitlyEnabled(.swiftTesting) ||
(initMode != .macro && testLibraryOptions.isEnabled(.swiftTesting)) {
if testLibraryOptions.isExplicitlyEnabled(.swiftTesting, swiftCommandState: swiftCommandState) ||
(initMode != .macro && testLibraryOptions.isEnabled(.swiftTesting, swiftCommandState: swiftCommandState)) {
supportedTestingLibraries.insert(.swiftTesting)
}

Expand Down
28 changes: 15 additions & 13 deletions Sources/Commands/SwiftTestCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,10 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
var results = [TestRunner.Result]()

// Run XCTest.
if options.testLibraryOptions.isEnabled(.xctest) {
// validate XCTest available on darwin based systems
if options.testLibraryOptions.isEnabled(.xctest, swiftCommandState: swiftCommandState) {
// Validate XCTest is available on Darwin-based systems. If it's not available and we're hitting this code
// path, that means the developer must have explicitly passed --enable-xctest (or the toolchain is
// corrupt, I suppose.)
let toolchain = try swiftCommandState.getTargetToolchain()
if case let .unsupported(reason) = try swiftCommandState.getHostToolchain().swiftSDK.xctestSupport {
if let reason {
Expand All @@ -276,7 +278,7 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
swiftCommandState: swiftCommandState,
library: .xctest
)
if result == .success, let testCount, testCount == 0 {
if result == .success, testCount == 0 {
results.append(.noMatchingTests)
} else {
results.append(result)
Expand Down Expand Up @@ -322,9 +324,9 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
}

// Run Swift Testing (parallel or not, it has a single entry point.)
if options.testLibraryOptions.isEnabled(.swiftTesting) {
if options.testLibraryOptions.isEnabled(.swiftTesting, swiftCommandState: swiftCommandState) {
lazy var testEntryPointPath = testProducts.lazy.compactMap(\.testEntryPointPath).first
if options.testLibraryOptions.isExplicitlyEnabled(.swiftTesting) || testEntryPointPath == nil {
if options.testLibraryOptions.isExplicitlyEnabled(.swiftTesting, swiftCommandState: swiftCommandState) || testEntryPointPath == nil {
results.append(
try await runTestProducts(
testProducts,
Expand Down Expand Up @@ -410,7 +412,7 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
public func run(_ swiftCommandState: SwiftCommandState) async throws {
do {
// Validate commands arguments
try self.validateArguments(observabilityScope: swiftCommandState.observabilityScope)
try self.validateArguments(swiftCommandState: swiftCommandState)
} catch {
swiftCommandState.observabilityScope.emit(error)
throw ExitCode.failure
Expand Down Expand Up @@ -464,7 +466,7 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
}
additionalArguments += commandLineArguments

if var xunitPath = options.xUnitOutput, options.testLibraryOptions.isEnabled(.xctest) {
if var xunitPath = options.xUnitOutput, options.testLibraryOptions.isEnabled(.xctest, swiftCommandState: swiftCommandState) {
// We are running Swift Testing, XCTest is also running in this session, and an xUnit path
// was specified. Make sure we don't stomp on XCTest's XML output by having Swift Testing
// write to a different path.
Expand Down Expand Up @@ -631,7 +633,7 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
/// Private function that validates the commands arguments
///
/// - Throws: if a command argument is invalid
private func validateArguments(observabilityScope: ObservabilityScope) throws {
private func validateArguments(swiftCommandState: SwiftCommandState) throws {
// Validation for --num-workers.
if let workers = options.numberOfWorkers {

Expand All @@ -646,13 +648,13 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
throw StringError("'--num-workers' must be greater than zero")
}

guard options.testLibraryOptions.isEnabled(.xctest) else {
guard options.testLibraryOptions.isEnabled(.xctest, swiftCommandState: swiftCommandState) else {
throw StringError("'--num-workers' is only supported when testing with XCTest")
}
}

if options._deprecated_shouldListTests {
observabilityScope.emit(warning: "'--list-tests' option is deprecated; use 'swift test list' instead")
swiftCommandState.observabilityScope.emit(warning: "'--list-tests' option is deprecated; use 'swift test list' instead")
}
}

Expand Down Expand Up @@ -733,7 +735,7 @@ extension SwiftTestCommand {
library: .swiftTesting
)

if testLibraryOptions.isEnabled(.xctest) {
if testLibraryOptions.isEnabled(.xctest, swiftCommandState: swiftCommandState) {
let testSuites = try TestingSupport.getTestSuites(
in: testProducts,
swiftCommandState: swiftCommandState,
Expand All @@ -749,9 +751,9 @@ extension SwiftTestCommand {
}
}

if testLibraryOptions.isEnabled(.swiftTesting) {
if testLibraryOptions.isEnabled(.swiftTesting, swiftCommandState: swiftCommandState) {
lazy var testEntryPointPath = testProducts.lazy.compactMap(\.testEntryPointPath).first
if testLibraryOptions.isExplicitlyEnabled(.swiftTesting) || testEntryPointPath == nil {
if testLibraryOptions.isExplicitlyEnabled(.swiftTesting, swiftCommandState: swiftCommandState) || testEntryPointPath == nil {
let additionalArguments = ["--list-tests"] + CommandLine.arguments.dropFirst()
let runner = TestRunner(
bundlePaths: testProducts.map(\.binaryPath),
Expand Down
27 changes: 15 additions & 12 deletions Sources/CoreCommands/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import struct PackageModel.EnabledSanitizers
import struct PackageModel.PackageIdentity
import class PackageModel.Manifest
import enum PackageModel.Sanitizer
@_spi(SwiftPMInternal) import struct PackageModel.SwiftSDK

import struct SPMBuildCore.BuildParameters

Expand Down Expand Up @@ -596,28 +597,30 @@ public struct TestLibraryOptions: ParsableArguments {
help: .private)
public var explicitlyEnableExperimentalSwiftTestingLibrarySupport: Bool?

private func isEnabled(_ library: BuildParameters.Testing.Library, `default`: Bool) -> Bool {
private func isEnabled(_ library: BuildParameters.Testing.Library, `default`: Bool, swiftCommandState: SwiftCommandState) -> Bool {
switch library {
case .xctest:
explicitlyEnableXCTestSupport ?? `default`
if let explicitlyEnableXCTestSupport {
return explicitlyEnableXCTestSupport
}
if let toolchain = try? swiftCommandState.getHostToolchain(),
toolchain.swiftSDK.xctestSupport == .supported {
return `default`
}
return false
case .swiftTesting:
explicitlyEnableSwiftTestingLibrarySupport ?? explicitlyEnableExperimentalSwiftTestingLibrarySupport ?? `default`
return explicitlyEnableSwiftTestingLibrarySupport ?? explicitlyEnableExperimentalSwiftTestingLibrarySupport ?? `default`
}
}

/// Test whether or not a given library is enabled.
public func isEnabled(_ library: BuildParameters.Testing.Library) -> Bool {
isEnabled(library, default: true)
public func isEnabled(_ library: BuildParameters.Testing.Library, swiftCommandState: SwiftCommandState) -> Bool {
isEnabled(library, default: true, swiftCommandState: swiftCommandState)
}

/// Test whether or not a given library was explicitly enabled by the developer.
public func isExplicitlyEnabled(_ library: BuildParameters.Testing.Library) -> Bool {
isEnabled(library, default: false)
}

/// The list of enabled testing libraries.
public var enabledTestingLibraries: [BuildParameters.Testing.Library] {
[.xctest, .swiftTesting].filter(isEnabled)
public func isExplicitlyEnabled(_ library: BuildParameters.Testing.Library, swiftCommandState: SwiftCommandState) -> Bool {
isEnabled(library, default: false, swiftCommandState: swiftCommandState)
}
}

Expand Down
12 changes: 12 additions & 0 deletions Sources/PackageModel/UserToolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,18 @@ public final class UserToolchain: Toolchain {
derivedSwiftCompiler: AbsolutePath,
fileSystem: any FileSystem
) -> (swiftCFlags: [String], linkerFlags: [String]) {
// If this is CommandLineTools all we need to add is a frameworks path.
if let frameworksPath = try? AbsolutePath(
validating: "../../Library/Developer/Frameworks",
relativeTo: resolveSymlinks(derivedSwiftCompiler).parentDirectory
), fileSystem.exists(frameworksPath.appending("Testing.framework")) {
return (swiftCFlags: [
"-F", frameworksPath.pathString
], linkerFlags: [
"-rpath", frameworksPath.pathString
])
}

guard let toolchainLibDir = try? toolchainLibDir(
swiftCompilerPath: derivedSwiftCompiler
) else {
Expand Down