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
17 changes: 14 additions & 3 deletions Sources/SwiftBuildSupport/PIFBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ package struct PIFBuilderParameters {
/// Additional rules for including a source or resource file in a target
let additionalFileRules: [FileRuleDescription]

package init(isPackageAccessModifierSupported: Bool, enableTestability: Bool, shouldCreateDylibForDynamicProducts: Bool, toolchainLibDir: AbsolutePath, pkgConfigDirectories: [AbsolutePath], supportedSwiftVersions: [SwiftLanguageVersion], pluginScriptRunner: PluginScriptRunner, disableSandbox: Bool, pluginWorkingDirectory: AbsolutePath, additionalFileRules: [FileRuleDescription]) {
/// Add rpaths which allow loading libraries adjacent to the current image at runtime. This is desirable
/// when launching build products from the build directory, but should often be disabled when deploying
/// the build products to a different location.
let addLocalRpaths: Bool

package init(isPackageAccessModifierSupported: Bool, enableTestability: Bool, shouldCreateDylibForDynamicProducts: Bool, toolchainLibDir: AbsolutePath, pkgConfigDirectories: [AbsolutePath], supportedSwiftVersions: [SwiftLanguageVersion], pluginScriptRunner: PluginScriptRunner, disableSandbox: Bool, pluginWorkingDirectory: AbsolutePath, additionalFileRules: [FileRuleDescription], addLocalRPaths: Bool) {
self.isPackageAccessModifierSupported = isPackageAccessModifierSupported
self.enableTestability = enableTestability
self.shouldCreateDylibForDynamicProducts = shouldCreateDylibForDynamicProducts
Expand All @@ -78,6 +83,7 @@ package struct PIFBuilderParameters {
self.disableSandbox = disableSandbox
self.pluginWorkingDirectory = pluginWorkingDirectory
self.additionalFileRules = additionalFileRules
self.addLocalRpaths = addLocalRPaths
}
}

Expand Down Expand Up @@ -406,6 +412,7 @@ public final class PIFBuilder {
delegate: packagePIFBuilderDelegate,
buildToolPluginResultsByTargetName: buildToolPluginResultsByTargetName,
createDylibForDynamicProducts: self.parameters.shouldCreateDylibForDynamicProducts,
addLocalRpaths: self.parameters.addLocalRpaths,
packageDisplayVersion: package.manifest.displayName,
fileSystem: self.fileSystem,
observabilityScope: self.observabilityScope
Expand Down Expand Up @@ -503,7 +510,8 @@ public final class PIFBuilder {
disableSandbox: Bool,
pluginWorkingDirectory: AbsolutePath,
pkgConfigDirectories: [Basics.AbsolutePath],
additionalFileRules: [FileRuleDescription]
additionalFileRules: [FileRuleDescription],
addLocalRpaths: Bool
) async throws -> String {
let parameters = PIFBuilderParameters(
buildParameters,
Expand All @@ -512,6 +520,7 @@ public final class PIFBuilder {
disableSandbox: disableSandbox,
pluginWorkingDirectory: pluginWorkingDirectory,
additionalFileRules: additionalFileRules,
addLocalRpaths: addLocalRpaths
)
let builder = Self(
graph: packageGraph,
Expand Down Expand Up @@ -773,7 +782,8 @@ extension PIFBuilderParameters {
pluginScriptRunner: PluginScriptRunner,
disableSandbox: Bool,
pluginWorkingDirectory: AbsolutePath,
additionalFileRules: [FileRuleDescription]
additionalFileRules: [FileRuleDescription],
addLocalRpaths: Bool
) {
self.init(
isPackageAccessModifierSupported: buildParameters.driverParameters.isPackageAccessModifierSupported,
Expand All @@ -786,6 +796,7 @@ extension PIFBuilderParameters {
disableSandbox: disableSandbox,
pluginWorkingDirectory: pluginWorkingDirectory,
additionalFileRules: additionalFileRules,
addLocalRPaths: addLocalRpaths,
)
}
}
9 changes: 9 additions & 0 deletions Sources/SwiftBuildSupport/PackagePIFBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ public final class PackagePIFBuilder {
/// * <rdar://56889224> Remove IDEPackageSupportCreateDylibsForDynamicProducts.
let createDylibForDynamicProducts: Bool

/// Add rpaths which allow loading libraries adjacent to the current image at runtime. This is desirable
/// when launching build products from the build directory, but should often be disabled when deploying
/// the build products to a different location.
let addLocalRpaths: Bool

/// Package display version, if any (i.e., it can be a version, branch or a git ref).
let packageDisplayVersion: String?

Expand Down Expand Up @@ -195,6 +200,7 @@ public final class PackagePIFBuilder {
delegate: PackagePIFBuilder.BuildDelegate,
buildToolPluginResultsByTargetName: [String: [BuildToolPluginInvocationResult]],
createDylibForDynamicProducts: Bool = false,
addLocalRpaths: Bool = true,
packageDisplayVersion: String?,
fileSystem: FileSystem,
observabilityScope: ObservabilityScope
Expand All @@ -208,6 +214,7 @@ public final class PackagePIFBuilder {
self.packageDisplayVersion = packageDisplayVersion
self.fileSystem = fileSystem
self.observabilityScope = observabilityScope
self.addLocalRpaths = addLocalRpaths
}

public init(
Expand All @@ -217,6 +224,7 @@ public final class PackagePIFBuilder {
delegate: PackagePIFBuilder.BuildDelegate,
buildToolPluginResultsByTargetName: [String: BuildToolPluginInvocationResult],
createDylibForDynamicProducts: Bool = false,
addLocalRpaths: Bool = true,
packageDisplayVersion: String?,
fileSystem: FileSystem,
observabilityScope: ObservabilityScope
Expand All @@ -227,6 +235,7 @@ public final class PackagePIFBuilder {
self.delegate = delegate
self.buildToolPluginResultsByTargetName = buildToolPluginResultsByTargetName.mapValues { [$0] }
self.createDylibForDynamicProducts = createDylibForDynamicProducts
self.addLocalRpaths = addLocalRpaths
self.packageDisplayVersion = packageDisplayVersion
self.fileSystem = fileSystem
self.observabilityScope = observabilityScope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -750,12 +750,21 @@ extension PackagePIFProjectBuilder {
//
// An imparted build setting on C will propagate back to both B and A.
// FIXME: -rpath should not be given if -static is
impartedSettings[.LD_RUNPATH_SEARCH_PATHS] =
["$(RPATH_ORIGIN)"] +
(impartedSettings[.LD_RUNPATH_SEARCH_PATHS] ?? ["$(inherited)"])
var rpaths: [String] = []
if let existingRpaths = impartedSettings[.LD_RUNPATH_SEARCH_PATHS] {
rpaths.append(contentsOf: existingRpaths)
}
if pifBuilder.addLocalRpaths {
rpaths.append("$(RPATH_ORIGIN)")
impartedSettings[.LD_RUNPATH_SEARCH_PATHS] = rpaths + ["$(inherited)"]
}

var impartedDebugSettings = impartedSettings
impartedDebugSettings[.LD_RUNPATH_SEARCH_PATHS]! += ["$(BUILT_PRODUCTS_DIR)/PackageFrameworks"]
if pifBuilder.addLocalRpaths {
// FIXME: Why is this rpath only added to the debug config? We should investigate reworking this.
rpaths.append("$(BUILT_PRODUCTS_DIR)/PackageFrameworks")
impartedDebugSettings[.LD_RUNPATH_SEARCH_PATHS] = rpaths + ["$(inherited)"]
}

self.project[keyPath: sourceModuleTargetKeyPath].common.addBuildConfig { id in
BuildConfig(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,13 @@ extension PackagePIFProjectBuilder {

if mainModule.type == .test {
// FIXME: we shouldn't always include both the deep and shallow bundle paths here, but for that we'll need rdar://31867023
settings[.LD_RUNPATH_SEARCH_PATHS] = [
"$(RPATH_ORIGIN)/Frameworks",
"$(RPATH_ORIGIN)/../Frameworks",
"$(inherited)"
]
if pifBuilder.addLocalRpaths {
settings[.LD_RUNPATH_SEARCH_PATHS] = [
"$(RPATH_ORIGIN)/Frameworks",
"$(RPATH_ORIGIN)/../Frameworks",
"$(inherited)"
]
}
settings[.GENERATE_INFOPLIST_FILE] = "YES"
settings[.SKIP_INSTALL] = "NO"
settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS].lazilyInitialize { ["$(inherited)"] }
Expand Down Expand Up @@ -1019,10 +1021,12 @@ extension PackagePIFProjectBuilder {

// A test-runner should always be adjacent to the dynamic library containing the tests,
// so add the appropriate rpaths.
settings[.LD_RUNPATH_SEARCH_PATHS] = [
"$(inherited)",
"$(RPATH_ORIGIN)"
]
if pifBuilder.addLocalRpaths {
settings[.LD_RUNPATH_SEARCH_PATHS] = [
"$(inherited)",
"$(RPATH_ORIGIN)"
]
}

let deploymentTargets = unitTestProduct.deploymentTargets
settings[.MACOSX_DEPLOYMENT_TARGET] = deploymentTargets?[.macOS] ?? nil
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftBuildSupport/SwiftBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,6 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
break
}

// TODO: shouldDisableLocalRpath
// TODO: shouldLinkStaticSwiftStdlib

return settings
Expand Down Expand Up @@ -1146,7 +1145,8 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
pluginScriptRunner: self.pluginConfiguration.scriptRunner,
disableSandbox: self.pluginConfiguration.disableSandbox,
pluginWorkingDirectory: self.pluginConfiguration.workDirectory,
additionalFileRules: additionalFileRules
additionalFileRules: additionalFileRules,
addLocalRpaths: !self.buildParameters.linkingParameters.shouldDisableLocalRpath
),
fileSystem: self.fileSystem,
observabilityScope: self.observabilityScope,
Expand Down
41 changes: 37 additions & 4 deletions Tests/SwiftBuildSupportTests/PIFBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import _InternalTestSupport
import Workspace

extension PIFBuilderParameters {
fileprivate static func constructDefaultParametersForTesting(temporaryDirectory: Basics.AbsolutePath) throws -> Self {
fileprivate static func constructDefaultParametersForTesting(temporaryDirectory: Basics.AbsolutePath, addLocalRpaths: Bool) throws -> Self {
self.init(
isPackageAccessModifierSupported: true,
enableTestability: false,
Expand All @@ -37,12 +37,13 @@ extension PIFBuilderParameters {
),
disableSandbox: false,
pluginWorkingDirectory: temporaryDirectory.appending(component: "plugin-working-dir"),
additionalFileRules: []
additionalFileRules: [],
addLocalRPaths: addLocalRpaths
)
}
}

fileprivate func withGeneratedPIF(fromFixture fixtureName: String, do doIt: (SwiftBuildSupport.PIF.TopLevelObject, TestingObservability) async throws -> ()) async throws {
fileprivate func withGeneratedPIF(fromFixture fixtureName: String, addLocalRpaths: Bool = true, do doIt: (SwiftBuildSupport.PIF.TopLevelObject, TestingObservability) async throws -> ()) async throws {
try await fixture(name: fixtureName) { fixturePath in
let observabilitySystem = ObservabilitySystem.makeForTesting()
let workspace = try Workspace(
Expand All @@ -58,7 +59,7 @@ fileprivate func withGeneratedPIF(fromFixture fixtureName: String, do doIt: (Swi
)
let builder = PIFBuilder(
graph: graph,
parameters: try PIFBuilderParameters.constructDefaultParametersForTesting(temporaryDirectory: fixturePath),
parameters: try PIFBuilderParameters.constructDefaultParametersForTesting(temporaryDirectory: fixturePath, addLocalRpaths: addLocalRpaths),
fileSystem: localFileSystem,
observabilityScope: observabilitySystem.topScope
)
Expand Down Expand Up @@ -238,4 +239,36 @@ struct PIFBuilderTests {
}
}
}

@Test func disablingLocalRpaths() async throws {
try await withGeneratedPIF(fromFixture: "Miscellaneous/Simple") { pif, observabilitySystem in
#expect(observabilitySystem.diagnostics.filter {
$0.severity == .error
}.isEmpty)

do {
let releaseConfig = try pif.workspace
.project(named: "Foo")
.target(named: "Foo")
.buildConfig(named: "Release")

#expect(releaseConfig.impartedBuildProperties.settings[.LD_RUNPATH_SEARCH_PATHS] == ["$(RPATH_ORIGIN)", "$(inherited)"])
}
}

try await withGeneratedPIF(fromFixture: "Miscellaneous/Simple", addLocalRpaths: false) { pif, observabilitySystem in
#expect(observabilitySystem.diagnostics.filter {
$0.severity == .error
}.isEmpty)

do {
let releaseConfig = try pif.workspace
.project(named: "Foo")
.target(named: "Foo")
.buildConfig(named: "Release")

#expect(releaseConfig.impartedBuildProperties.settings[.LD_RUNPATH_SEARCH_PATHS] == nil)
}
}
}
}