Skip to content
Draft
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: 8 additions & 0 deletions Fixtures/Coverage/Simple/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
26 changes: 26 additions & 0 deletions Fixtures/Coverage/Simple/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// swift-tools-version: 6.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Simple",
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "Simple",
targets: ["Simple"]
),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "Simple"
),
.testTarget(
name: "SimpleTests",
dependencies: ["Simple"]
),
]
)
10 changes: 10 additions & 0 deletions Fixtures/Coverage/Simple/Sources/Simple/Simple.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book

public func greet(name: String = "world") -> String {
return "Hello, \(name)!"
}

public func libA() -> String {
return "libA"
}
24 changes: 24 additions & 0 deletions Fixtures/Coverage/Simple/Tests/SimpleTests/SimpleTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Testing
import XCTest
@testable import Simple

@Test(
arguments: [
"Bob",
"Alice",
"",
]
)
func testGreet(
name: String
) async throws {
let actual = greet(name: name)

#expect(actual == "Hello, \(name)!")
}

final class SimpleTests: XCTestCase {
func testExample() throws {
XCTAssertEqual(libA(), "libA", "Actual is not as expected")
}
}
4 changes: 2 additions & 2 deletions Fixtures/Miscellaneous/MultipleExecutables/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ let package = Package(
.library(name: "lib1", targets: ["lib1"]),
],
targets: [
.target(name: "exec1"),
.target(name: "exec2"),
.target(name: "exec1", dependencies: ["lib1"]),
.target(name: "exec2", dependencies: ["lib1"]),
.target(name: "lib1"),
]
)
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
import lib1

foo()
print("1")
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
import lib1

foo()
print("2")
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public func foo() {
print("In lib")
}
9 changes: 7 additions & 2 deletions Sources/Basics/FileSystem/AbsolutePath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,19 @@ public struct AbsolutePath: Hashable, Sendable {
/// The input string will be normalized if needed, as described in the
/// documentation for AbsolutePath.
public init(validating pathString: String) throws {
self.underlying = try .init(validating: pathString)
self.underlying = try .init(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: I would favor TSCAbsolutePath(...) instead of the harder to read .init(...).

validating: pathString.trimmingCharacters(in: .whitespacesAndNewlines),
)
}

/// Initializes an AbsolutePath from a string that may be either absolute
/// or relative; if relative, `basePath` is used as the anchor; if absolute,
/// it is used as is, and in this case `basePath` is ignored.
public init(validating pathString: String, relativeTo basePath: AbsolutePath) throws {
self.underlying = try .init(validating: pathString, relativeTo: basePath.underlying)
self.underlying = try .init(
validating: pathString.trimmingCharacters(in: .whitespacesAndNewlines),
relativeTo: basePath.underlying,
)
}

/// Initializes the AbsolutePath by concatenating a relative path to an
Expand Down
6 changes: 4 additions & 2 deletions Sources/Basics/FileSystem/RelativePath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import Foundation
import struct TSCBasic.RelativePath

// public for transition
Expand Down Expand Up @@ -40,7 +40,9 @@ public struct RelativePath: Hashable, Sendable {

/// Convenience initializer that verifies that the path is relative.
public init(validating pathString: String) throws {
self.underlying = try .init(validating: pathString)
self.underlying = try .init(
validating: pathString.trimmingCharacters(in: .whitespacesAndNewlines),
)
}

/// Directory component. For a relative path without any path separators,
Expand Down
32 changes: 29 additions & 3 deletions Sources/Commands/SwiftTestCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ArgumentParser

@_spi(SwiftPMInternal)
import Basics
import struct Basics.Triple

import _Concurrency

Expand Down Expand Up @@ -597,7 +598,11 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
for product in testProducts {
// Export the codecov data as JSON.
let jsonPath = productsBuildParameters.codeCovAsJSONPath(packageName: rootManifest.displayName)
try await exportCodeCovAsJSON(to: jsonPath, testBinary: product.binaryPath, swiftCommandState: swiftCommandState)
try await exportCodeCovAsJSON(
to: jsonPath,
testBinary: product.binaryPath,
swiftCommandState: swiftCommandState,
)
}
}

Expand All @@ -619,7 +624,6 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
}
}
args += ["-o", productsBuildParameters.codeCovDataFile.pathString]

try await AsyncProcess.checkNonZeroExit(arguments: args)
}

Expand All @@ -632,11 +636,18 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
// Export using the llvm-cov tool.
let llvmCov = try swiftCommandState.getTargetToolchain().getLLVMCov()
let (productsBuildParameters, _) = try swiftCommandState.buildParametersForTest(options: self.options)
let archArgs: [String] = if let arch = productsBuildParameters.triple.llvmCovArchArgument {
// let archArgs: [String] = if let arch = productsBuildParameters.triple.arch {
["--arch", "\(arch)"]
} else {
[]
}
let args = [
llvmCov.pathString,
"export",
"-instr-profile=\(productsBuildParameters.codeCovDataFile)",
testBinary.pathString
] + archArgs + [
testBinary.pathString,
]
let result = try await AsyncProcess.popen(arguments: args)

Expand Down Expand Up @@ -709,6 +720,21 @@ extension SwiftTestCommand {
}
}

fileprivate extension Triple {
var llvmCovArchArgument: String? {
guard let arch = self.arch else {
return nil
}
switch arch {
case .aarch64:
// macOS uses arm64, Linux might use aarch64
return ProcessInfo.hostOperatingSystem == .macOS ? "arm64" : "aarch64"
default:
return "\(arch)"
}
}
}

extension SwiftTestCommand {
struct Last: SwiftCommand {
@OptionGroup(visibility: .hidden)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ extension PackagePIFProjectBuilder {
/// we also construct a testable version of said executable.
mutating func makeTestableExecutableSourceModule(_ executableModule: PackageGraph.ResolvedModule) throws {
precondition(executableModule.type == .executable)
guard self.package.manifest.toolsVersion >= .v5_5 else { return }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: For reference, this is the comment on the original PIF builder (which I preserved in the func doc comment above):

// If we're building an executable and the tools version is new enough, 
// we also construct a testable version of the executable.
if manifest.toolsVersion >= .v5_5 { ... }

So maybe Swift 5.5 somehow made this possible? Have you tested this in toolchains older than 5.5?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SwiftBuild integration in SwiftPM is occurring on branch main, and I don't expect we will support swift 5.x

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packages below tools version 5.5 shouldn't generate this target representing the testable version of an executable since that feature isn't available. The tools version of a package is independent of the version of the tools themselves. I think the underlying issue here is likely that --target is not discovering the regular variant of the target, which is created in all tools versions. My best guess is that maybe that target got subsumed by a product target at the PIF layer, and the lookup code doesn't account for that.


let inputResourceBundleName: String? = if mainModuleTargetNamesWithResources.contains(executableModule.name) {
resourceBundleName(forModuleName: executableModule.name)
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftBuildSupport/SwiftBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1077,8 +1077,8 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {

private static func constructTestingSettingsOverrides(from parameters: BuildParameters.Testing) -> [String: String] {
var settings: [String: String] = [:]
// TODO: enableCodeCoverage
// explicitlyEnabledTestability

settings["CLANG_COVERAGE_MAPPING"] = parameters.enableCodeCoverage ? "YES" : "NO"

switch parameters.explicitlyEnabledTestability {
case true:
Expand Down
7 changes: 7 additions & 0 deletions Sources/_InternalTestSupport/SwiftTesting+TraitsBug.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ extension Trait where Self == Testing.Bug {
)
}

public static var IssueWindowsPathTestsFailures: Self {
.issue(
"https://github.com/swiftlang/swift-package-manager/issues/8511",
relationship: .defect,
)
}

public static var IssueWindowsCannotSaveAttachment: Self {
// error: unable to write file 'C:\Users\ContainerAdministrator\AppData\Local\Temp\CFamilyTargets_CDynamicLookup.hNxGHC\CFamilyTargets_CDynamicLookup\.build\x86_64-unknown-windows-msvc\Intermediates.noindex\CDynamicLookup.build\Release-windows\CDynamicLookup.build\Objects-normal\x86_64\CDynamicLookup.LinkFileList': No such file or directory (2)
.issue(
Expand Down
Loading