diff --git a/Sources/Build/BuildDescription/ClangTargetBuildDescription.swift b/Sources/Build/BuildDescription/ClangTargetBuildDescription.swift index e821ffa2331..7f9d1cf4f61 100644 --- a/Sources/Build/BuildDescription/ClangTargetBuildDescription.swift +++ b/Sources/Build/BuildDescription/ClangTargetBuildDescription.swift @@ -311,6 +311,18 @@ public final class ClangTargetBuildDescription { args += ["-I", includeSearchPath.pathString] } + // FIXME: Remove this once it becomes possible to express this dependency in a package manifest. + // + // On Linux/Android swift-corelibs-foundation depends on dispatch library which is + // currently shipped with the Swift toolchain. + if (triple.isLinux() || triple.isAndroid()) && self.package.id == .plain("swift-corelibs-foundation") { + let swiftCompilerPath = self.buildParameters.toolchain.swiftCompilerPath + let toolchainResourcesPath = swiftCompilerPath.parentDirectory + .parentDirectory + .appending(components: ["lib", "swift"]) + args += ["-I", toolchainResourcesPath.pathString] + } + // suppress warnings if the package is remote if self.package.isRemote { args += ["-w"] diff --git a/Sources/SPMTestSupport/MockBuildTestHelper.swift b/Sources/SPMTestSupport/MockBuildTestHelper.swift index 83662600628..28b4cf55c4b 100644 --- a/Sources/SPMTestSupport/MockBuildTestHelper.swift +++ b/Sources/SPMTestSupport/MockBuildTestHelper.swift @@ -20,7 +20,7 @@ import SPMBuildCore import TSCUtility import XCTest -public struct MockToolchain: PackageModel.Toolchain { +package struct MockToolchain: PackageModel.Toolchain { #if os(Windows) public let librarianPath = AbsolutePath("/fake/path/to/link.exe") #elseif os(iOS) || os(macOS) || os(tvOS) || os(watchOS) @@ -28,15 +28,15 @@ public struct MockToolchain: PackageModel.Toolchain { #else public let librarianPath = AbsolutePath("/fake/path/to/llvm-ar") #endif - public let swiftCompilerPath = AbsolutePath("/fake/path/to/swiftc") - public let includeSearchPaths = [AbsolutePath]() - public let librarySearchPaths = [AbsolutePath]() - public let swiftResourcesPath: AbsolutePath? = nil - public let swiftStaticResourcesPath: AbsolutePath? = nil - public let sdkRootPath: AbsolutePath? = nil - public let extraFlags = PackageModel.BuildFlags() - public let installedSwiftPMConfiguration = InstalledSwiftPMConfiguration.default - public let providedLibraries = [LibraryMetadata]() + package let swiftCompilerPath = AbsolutePath("/fake/path/to/swiftc") + package let includeSearchPaths = [AbsolutePath]() + package let librarySearchPaths = [AbsolutePath]() + package let swiftResourcesPath: AbsolutePath? + package let swiftStaticResourcesPath: AbsolutePath? = nil + package let sdkRootPath: AbsolutePath? = nil + package let extraFlags = PackageModel.BuildFlags() + package let installedSwiftPMConfiguration = InstalledSwiftPMConfiguration.default + package let providedLibraries = [LibraryMetadata]() public func getClangCompiler() throws -> AbsolutePath { "/fake/path/to/clang" @@ -50,7 +50,9 @@ public struct MockToolchain: PackageModel.Toolchain { #endif } - public init() {} + package init(swiftResourcesPath: AbsolutePath? = nil) { + self.swiftResourcesPath = swiftResourcesPath + } } extension Basics.Triple { @@ -70,7 +72,7 @@ public let defaultTargetTriple: String = hostTriple.tripleString(forPlatformVers public let defaultTargetTriple: String = hostTriple.tripleString #endif -public func mockBuildParameters( +package func mockBuildParameters( buildPath: AbsolutePath = "/path/to/build", config: BuildConfiguration = .debug, toolchain: PackageModel.Toolchain = MockToolchain(), diff --git a/Tests/BuildTests/ClangTargetBuildDescriptionTests.swift b/Tests/BuildTests/ClangTargetBuildDescriptionTests.swift index 7b8a01802d2..eabfee6ad10 100644 --- a/Tests/BuildTests/ClangTargetBuildDescriptionTests.swift +++ b/Tests/BuildTests/ClangTargetBuildDescriptionTests.swift @@ -30,6 +30,27 @@ final class ClangTargetBuildDescriptionTests: XCTestCase { XCTAssertTrue(try targetDescription.basicArguments().contains("-w")) } + func testSwiftCorelibsFoundationIncludeWorkaround() throws { + let toolchain = MockToolchain(swiftResourcesPath: AbsolutePath("/fake/path/lib/swift")) + + let macosParameters = mockBuildParameters(toolchain: toolchain, targetTriple: .macOS) + let linuxParameters = mockBuildParameters(toolchain: toolchain, targetTriple: .arm64Linux) + let androidParameters = mockBuildParameters(toolchain: toolchain, targetTriple: .arm64Android) + + let macDescription = try makeTargetBuildDescription("swift-corelibs-foundation", + buildParameters: macosParameters) + XCTAssertFalse(try macDescription.basicArguments().contains("\(macosParameters.toolchain.swiftResourcesPath!)")) + + let linuxDescription = try makeTargetBuildDescription("swift-corelibs-foundation", + buildParameters: linuxParameters) + print(try linuxDescription.basicArguments()) + XCTAssertTrue(try linuxDescription.basicArguments().contains("\(linuxParameters.toolchain.swiftResourcesPath!)")) + + let androidDescription = try makeTargetBuildDescription("swift-corelibs-foundation", + buildParameters: androidParameters) + XCTAssertTrue(try androidDescription.basicArguments().contains("\(androidParameters.toolchain.swiftResourcesPath!)")) + } + private func makeClangTarget() throws -> ClangTarget { try ClangTarget( name: "dummy",