Skip to content

Swift SDKs: implement swiftResourcesPath #6717

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

Merged
merged 6 commits into from
Sep 7, 2023
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
13 changes: 13 additions & 0 deletions Sources/Build/BuildDescription/ProductBuildDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
derivedProductType = self.product.type
}

var isLinkingStaticStdlib = false
switch derivedProductType {
case .macro:
throw InternalError("macro not supported") // should never be reached
Expand All @@ -213,11 +214,13 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
args += self.deadStripArguments
case .executable, .snippet:
// Link the Swift stdlib statically, if requested.
// TODO: unify this logic with SwiftTargetBuildDescription.stdlibArguments
if self.buildParameters.shouldLinkStaticSwiftStdlib {
if self.buildParameters.targetTriple.isDarwin() {
self.observabilityScope.emit(.swiftBackDeployError)
} else if self.buildParameters.targetTriple.isSupportingStaticStdlib {
args += ["-static-stdlib"]
isLinkingStaticStdlib = true
}
}
args += ["-emit-executable"]
Expand All @@ -243,6 +246,16 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
throw InternalError("unexpectedly asked to generate linker arguments for a plugin product")
}

if let resourcesPath = self.buildParameters.toolchain.swiftResourcesPath(isStatic: isLinkingStaticStdlib) {
args += ["-resource-dir", "\(resourcesPath)"]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@MaxDesiatov is it correct to rely on interpolation here instead of pathString?

Copy link
Contributor

@tomerd tomerd Jul 20, 2023

Choose a reason for hiding this comment

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

should this just move into the if self.buildParameters.shouldLinkStaticSwiftStdlib branch? its used only there it seems hmm read this wrong

Copy link
Contributor

Choose a reason for hiding this comment

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

}

// clang resources are always in lib/swift/
if let dynamicResourcesPath = self.buildParameters.toolchain.swiftResourcesPath {
let clangResourcesPath = dynamicResourcesPath.appending("clang")
args += ["-Xclang-linker", "-resource-dir", "-Xclang-linker", "\(clangResourcesPath)"]
}

// Set rpath such that dynamic libraries are looked up
// adjacent to the product.
if self.buildParameters.targetTriple.isLinux() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -799,12 +799,18 @@ public final class SwiftTargetBuildDescription {
}

private var stdlibArguments: [String] {
if self.buildParameters.shouldLinkStaticSwiftStdlib,
self.buildParameters.targetTriple.isSupportingStaticStdlib
{
return ["-static-stdlib"]
} else {
return []
var arguments: [String] = []

let isLinkingStaticStdlib = self.buildParameters.shouldLinkStaticSwiftStdlib
&& self.buildParameters.targetTriple.isSupportingStaticStdlib
if isLinkingStaticStdlib {
arguments += ["-static-stdlib"]
}

if let resourcesPath = self.buildParameters.toolchain.swiftResourcesPath(isStatic: isLinkingStaticStdlib) {
arguments += ["-resource-dir", "\(resourcesPath)"]
}

return arguments
}
}
16 changes: 15 additions & 1 deletion Sources/PackageModel/Toolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ public protocol Toolchain {
/// Path of the `swiftc` compiler.
var swiftCompilerPath: AbsolutePath { get }

/// Path to `lib/swift`
var swiftResourcesPath: AbsolutePath? { get }

/// Path to `lib/swift_static`
var swiftStaticResourcesPath: AbsolutePath? { get }

/// Whether the used compiler is from a open source development toolchain.
var isSwiftDevelopmentToolchain: Bool { get }

Expand Down Expand Up @@ -81,7 +87,15 @@ extension Toolchain {
return try AbsolutePath(validating: "../../lib", relativeTo: resolveSymlinks(swiftCompilerPath))
}
}


/// Returns the appropriate Swift resources directory path.
///
/// - Parameter static: Controls whether to use the static or dynamic
/// resources directory.
public func swiftResourcesPath(isStatic: Bool) -> AbsolutePath? {
isStatic ? swiftStaticResourcesPath : swiftResourcesPath
}

public var extraCCFlags: [String] {
extraFlags.cCompilerFlags
}
Expand Down
10 changes: 10 additions & 0 deletions Sources/PackageModel/UserToolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ public final class UserToolchain: Toolchain {
/// An array of paths to search for libraries at link time.
public let librarySearchPaths: [AbsolutePath]

/// Path containing Swift resources for dynamic linking.
public var swiftResourcesPath: AbsolutePath? {
destination.pathsConfiguration.swiftResourcesPath
}

/// Path containing Swift resources for static linking.
public var swiftStaticResourcesPath: AbsolutePath? {
destination.pathsConfiguration.swiftStaticResourcesPath
}

/// Additional flags to be passed to the build tools.
public var extraFlags: BuildFlags

Expand Down
33 changes: 32 additions & 1 deletion Tests/BuildTests/BuildPlanTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3570,6 +3570,9 @@ final class BuildPlanTests: XCTestCase {
Manifest.createRootManifest(
displayName: "Pkg",
path: "/Pkg",
products: [
ProductDescription(name: "exe", type: .executable, targets: ["exe"]),
],
targets: [
TargetDescription(name: "exe", dependencies: ["lib"]),
TargetDescription(name: "lib", dependencies: []),
Expand All @@ -3587,7 +3590,11 @@ final class BuildPlanTests: XCTestCase {
],
rootPaths: try UserToolchain.default.swiftSDK.toolset.rootPaths
),
pathsConfiguration: .init(sdkRootPath: "/fake/sdk")
pathsConfiguration: .init(
sdkRootPath: "/fake/sdk",
swiftResourcesPath: "/fake/lib/swift",
swiftStaticResourcesPath: "/fake/lib/swift_static"
)
)
let mockToolchain = try UserToolchain(swiftSDK: userSwiftSDK)
let extraBuildParameters = mockBuildParameters(toolchain: mockToolchain,
Expand Down Expand Up @@ -3616,6 +3623,7 @@ final class BuildPlanTests: XCTestCase {
let exe = try result.target(for: "exe").swiftTarget().compileArguments()
XCTAssertMatch(exe, [
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
"-resource-dir", "/fake/lib/swift",
.anySequence,
"-swift-flag-from-json",
.anySequence,
Expand All @@ -3625,6 +3633,29 @@ final class BuildPlanTests: XCTestCase {
.anySequence,
"-Xcc", "-clang-command-line-flag"
])

let exeProduct = try result.buildProduct(for: "exe").linkArguments()
XCTAssertMatch(exeProduct, [.anySequence, "-resource-dir", "/fake/lib/swift", "-Xclang-linker", "-resource-dir", "-Xclang-linker", "/fake/lib/swift/clang", .anySequence])

let staticBuildParameters = {
var copy = extraBuildParameters
copy.shouldLinkStaticSwiftStdlib = true
// pick a triple with support for static linking
copy.targetTriple = .x86_64Linux
return copy
}()
let staticResult = try BuildPlanResult(plan: BuildPlan(
buildParameters: staticBuildParameters,
graph: graph,
fileSystem: fs,
observabilityScope: observability.topScope
))

let staticExe = try staticResult.target(for: "exe").swiftTarget().compileArguments()
XCTAssertMatch(staticExe, [.anySequence, "-resource-dir", "/fake/lib/swift_static", .anySequence])

let staticExeProduct = try staticResult.buildProduct(for: "exe").linkArguments()
XCTAssertMatch(staticExeProduct, [.anySequence, "-resource-dir", "/fake/lib/swift_static", "-Xclang-linker", "-resource-dir", "-Xclang-linker", "/fake/lib/swift/clang", .anySequence])
}

func testUserToolchainWithToolsetCompileFlags() throws {
Expand Down
2 changes: 2 additions & 0 deletions Tests/BuildTests/MockBuildTestHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ struct MockToolchain: PackageModel.Toolchain {
let swiftCompilerPath = AbsolutePath("/fake/path/to/swiftc")
let includeSearchPaths = [AbsolutePath]()
let librarySearchPaths = [AbsolutePath]()
let swiftResourcesPath: AbsolutePath? = nil
let swiftStaticResourcesPath: AbsolutePath? = nil
let isSwiftDevelopmentToolchain = false
let swiftPluginServerPath: AbsolutePath? = nil
let extraFlags = PackageModel.BuildFlags()
Expand Down