Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@

import struct SPMBuildCore.BuildSystemProvider
import enum PackageModel.BuildConfiguration
import class PackageModel.UserToolchain

extension BuildSystemProvider.Kind {

@available(*, deprecated, message: "use binPath(for:scrathPath:triple) instead")
public func binPathSuffixes(for config: BuildConfiguration) -> [String] {
let suffix: String

#if os(Linux)
suffix = "-linux"
#elseif os(Windows)
suffix = "-windows"
suffix = "-windows"
#else
suffix = ""
#endif
Expand All @@ -34,4 +36,40 @@ extension BuildSystemProvider.Kind {
return ["apple", "Products" , "\(config)".capitalized + suffix]
}
}

public func binPath(
for config: BuildConfiguration,
scratchPath: [String] = [".build"],
triple: String? = nil,
) throws -> [String] {
let suffix: String

#if os(Linux)
suffix = "-linux"
#elseif os(Windows)
suffix = "-windows"
#else
suffix = ""
#endif

let tripleString: String
if let triple {
tripleString = triple
} else {
do {
tripleString = try UserToolchain.default.targetTriple.platformBuildPathComponent
} catch {
tripleString = ""
}
}
switch self {
case .native:
return scratchPath + [tripleString, "\(config)".lowercased()]
case .swiftbuild:
return scratchPath + [tripleString, "Products", "\(config)".capitalized + suffix]
case .xcode:
return scratchPath + ["apple", "Products", "\(config)".capitalized + suffix]
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ extension Trait where Self == Testing.ConditionTrait {
}
}

/// Enabled if toolsupm suported SDK Dependent Tests
public static var requiresSDKDependentTestsSupport: Self {
enabled("skipping because test environment doesn't support this test") {
(try? UserToolchain.default)!.supportsSDKDependentTests()
}
}

// Enabled if the toolchain has supported features
public static var supportsSupportedFeatures: Self {
enabled("skipping because test environment compiler doesn't support `-print-supported-features`") {
Expand Down
102 changes: 73 additions & 29 deletions Tests/BuildTests/BuildSystemDelegateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,94 @@
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift project authors
// Copyright (c) 2024-2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Foundation

import PackageModel
import _InternalTestSupport
import XCTest
import Testing

import var TSCBasic.localFileSystem

final class BuildSystemDelegateTests: XCTestCase {
func testDoNotFilterLinkerDiagnostics() async throws {
try XCTSkipIf(!UserToolchain.default.supportsSDKDependentTests(), "skipping because test environment doesn't support this test")
try await fixtureXCTest(name: "Miscellaneous/DoNotFilterLinkerDiagnostics") { fixturePath in
#if !os(macOS)
// These linker diagnostics are only produced on macOS.
try XCTSkipIf(true, "test is only supported on macOS")
#endif
let (fullLog, _) = try await executeSwiftBuild(fixturePath, buildSystem: .native)
XCTAssertTrue(fullLog.contains("ld: warning: search path 'foobar' not found"), "log didn't contain expected linker diagnostics")
@Suite(
.tags(
.TestSize.large,
)
)
struct BuildSystemDelegateTests {
@Test(
.requiresSDKDependentTestsSupport,
.requireHostOS(.macOS), // These linker diagnostics are only produced on macOS.
arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms),
)
func doNotFilterLinkerDiagnostics(
data: BuildData,
) async throws {
try await fixture(name: "Miscellaneous/DoNotFilterLinkerDiagnostics") { fixturePath in
let (stdout, stderr) = try await executeSwiftBuild(
fixturePath,
configuration: data.config,
// extraArgs: ["--verbose"],
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: can we remove this comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll remove it in a subsequent PR.

buildSystem: data.buildSystem,
)
switch data.buildSystem {
case .native:
#expect(
stdout.contains("ld: warning: search path 'foobar' not found"),
"log didn't contain expected linker diagnostics. stderr: '\(stderr)')",
)
case .swiftbuild:
#expect(
stderr.contains("warning: Search path 'foobar' not found"),
"log didn't contain expected linker diagnostics. stderr: '\(stdout)",
)
#expect(
!stdout.contains("warning: Search path 'foobar' not found"),
"log didn't contain expected linker diagnostics. stderr: '\(stderr)')",
)
case .xcode:
Issue.record("Test expectation has not be implemented")
}
}
}

func testFilterNonFatalCodesignMessages() async throws {
try XCTSkipOnWindows(because: "https://github.com/swiftlang/swift-package-manager/issues/8540: Package fails to build when the test is being executed")

try XCTSkipIf(!UserToolchain.default.supportsSDKDependentTests(), "skipping because test environment doesn't support this test")
// Note: we can re-use the `TestableExe` fixture here since we just need an executable.
#if os(Windows)
let executableExt = ".exe"
#else
let executableExt = ""
#endif
try await fixtureXCTest(name: "Miscellaneous/TestableExe") { fixturePath in
_ = try await executeSwiftBuild(fixturePath, buildSystem: .native)
let execPath = fixturePath.appending(components: ".build", "debug", "TestableExe1\(executableExt)")
XCTAssertTrue(localFileSystem.exists(execPath), "executable not found at '\(execPath)'")
try localFileSystem.removeFileTree(execPath)
let (fullLog, _) = try await executeSwiftBuild(fixturePath, buildSystem: .native)
XCTAssertFalse(fullLog.contains("replacing existing signature"), "log contained non-fatal codesigning messages")
@Test(
.issue("https://github.com/swiftlang/swift-package-manager/issues/8540", relationship: .defect), // Package fails to build when the test is being executed"
.requiresSDKDependentTestsSupport,
arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms),
)
func filterNonFatalCodesignMessages(
data: BuildData,
) async throws {
try await withKnownIssue(isIntermittent: true) {
// Note: we can re-use the `TestableExe` fixture here since we just need an executable.
try await fixture(name: "Miscellaneous/TestableExe") { fixturePath in
_ = try await executeSwiftBuild(
fixturePath,
configuration: data.config,
buildSystem: data.buildSystem,
)
let execPath = try fixturePath.appending(
components: data.buildSystem.binPath(for: data.config) + [executableName("TestableExe1")]
)
expectFileExists(at: execPath)
try localFileSystem.removeFileTree(execPath)
let (stdout, stderr) = try await executeSwiftBuild(
fixturePath,
configuration: data.config,
buildSystem: data.buildSystem,
)
#expect(!stdout.contains("replacing existing signature"), "log contained non-fatal codesigning messages stderr: '\(stderr)'")
#expect(!stderr.contains("replacing existing signature"), "log contained non-fatal codesigning messages. stdout: '\(stdout)'")
}
} when: {
ProcessInfo.hostOperatingSystem == .windows
}
}
}
43 changes: 13 additions & 30 deletions Tests/CommandsTests/BuildCommandTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ struct SanitierTests {
}

@Suite(
.serialized, // to limit the number of swift executable running.
.tags(
Tag.TestSize.large,
Tag.Feature.Command.Build,
Expand Down Expand Up @@ -165,18 +164,11 @@ struct BuildCommandTestCases {
// Test is not implemented for Xcode build system
try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in
let fullPath = try resolveSymlinks(fixturePath)

let rootScrathPath = fullPath.appending(component: ".build")
let targetPath: AbsolutePath
if buildSystem == .xcode {
targetPath = rootScrathPath
} else {
targetPath = try rootScrathPath.appending(component: UserToolchain.default.targetTriple.platformBuildPathComponent)
}

let targetPath = try fullPath.appending(components: buildSystem.binPath(for: configuration))
let path = try await self.execute(["--show-bin-path"], packagePath: fullPath, configuration: configuration, buildSystem: buildSystem).stdout.trimmingCharacters(in: .whitespacesAndNewlines)
#expect(
AbsolutePath(path).pathString == targetPath
.appending(components: buildSystem.binPathSuffixes(for: configuration)).pathString
AbsolutePath(path).pathString == targetPath.pathString
)
}
}
Expand Down Expand Up @@ -288,29 +280,24 @@ struct BuildCommandTestCases {
}

@Test(
.SWBINTTODO("Test fails because of a difference in the build layout. This needs to be updated to the expected path"),
arguments: SupportedBuildSystemOnPlatform, BuildConfiguration.allCases
arguments: getBuildData(for: SupportedBuildSystemOnPlatform),
)
func symlink(
buildSystem: BuildSystemProvider.Kind,
configuration: BuildConfiguration,
data: BuildData,
) async throws {
try await withKnownIssue {
let buildSystem = data.buildSystem
let configuration = data.config
try await withKnownIssue(isIntermittent: true) {
try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in
let fullPath = try resolveSymlinks(fixturePath)
let targetPath = try fullPath.appending(components:
".build",
UserToolchain.default.targetTriple.platformBuildPathComponent
)
// Test symlink.
let buildDir = fullPath.appending(components: ".build")
try await self.execute(packagePath: fullPath, configuration: configuration, buildSystem: buildSystem)
let actualDebug = try resolveSymlinks(buildDir.appending(components: buildSystem.binPathSuffixes(for: configuration)))
let expectedDebug = targetPath.appending(components: buildSystem.binPathSuffixes(for: configuration))
let actualDebug = try resolveSymlinks(fullPath.appending(components: buildSystem.binPath(for: configuration)))
let expectedDebug = try fullPath.appending(components: buildSystem.binPath(for: configuration))
#expect(actualDebug == expectedDebug)
}
} when: {
buildSystem != .native
ProcessInfo.hostOperatingSystem == .windows
}
}

Expand Down Expand Up @@ -1125,10 +1112,9 @@ struct BuildCommandTestCases {
return try SupportedBuildSystemOnPlatform.map { buildSystem in
let triple = try UserToolchain.default.targetTriple.withoutVersion()
let base = try RelativePath(validating: ".build")
let debugFolderComponents = buildSystem.binPathSuffixes(for: .debug)
let path = try base.appending(components: buildSystem.binPath(for: .debug, scratchPath: []))
switch buildSystem {
case .xcode:
let path = base.appending(components: debugFolderComponents)
return (
buildSystem,
triple.platformName() == "macosx" ? path.appending("ExecutableNew") : path
Expand All @@ -1137,8 +1123,6 @@ struct BuildCommandTestCases {
.appending("\(triple).swiftsourceinfo")
)
case .swiftbuild:
let path = base.appending(triple.tripleString)
.appending(components: debugFolderComponents)
return (
buildSystem,
triple.platformName() == "macosx" ? path.appending("ExecutableNew") : path
Expand All @@ -1149,8 +1133,7 @@ struct BuildCommandTestCases {
case .native:
return (
buildSystem,
base.appending(components: debugFolderComponents)
.appending("ExecutableNew.build")
path.appending("ExecutableNew.build")
.appending("main.swift.o")
)
}
Expand Down
Loading