Skip to content

Commit 9890b21

Browse files
committed
Add an rpath flag to disable the default of looking in the local directory for shared libraries
This is useful when deploying build products, as most executables are not installed in the same directory as libraries and system libraries do not need it for system paths. Use the new flag when installing SwiftPM itself and the {Manifest,Plugin}API libraries on ELF platforms.
1 parent d0ae2c5 commit 9890b21

File tree

8 files changed

+118
-8
lines changed

8 files changed

+118
-8
lines changed

Sources/Build/BuildDescription/ProductBuildDescription.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,14 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
257257
}
258258

259259
// Set rpath such that dynamic libraries are looked up
260-
// adjacent to the product.
261-
if self.buildParameters.targetTriple.isLinux() {
262-
args += ["-Xlinker", "-rpath=$ORIGIN"]
263-
} else if self.buildParameters.targetTriple.isDarwin() {
264-
let rpath = self.product.type == .test ? "@loader_path/../../../" : "@loader_path"
265-
args += ["-Xlinker", "-rpath", "-Xlinker", rpath]
260+
// adjacent to the product, unless overridden.
261+
if !self.buildParameters.shouldDisableLocalRpath {
262+
if self.buildParameters.targetTriple.isLinux() {
263+
args += ["-Xlinker", "-rpath=$ORIGIN"]
264+
} else if self.buildParameters.targetTriple.isDarwin() {
265+
let rpath = self.product.type == .test ? "@loader_path/../../../" : "@loader_path"
266+
args += ["-Xlinker", "-rpath", "-Xlinker", rpath]
267+
}
266268
}
267269
args += ["@\(self.linkFileListPath.pathString)"]
268270

Sources/CoreCommands/Options.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,10 @@ public struct LinkerOptions: ParsableArguments {
524524
/// If should link the Swift stdlib statically.
525525
@Flag(name: .customLong("static-swift-stdlib"), inversion: .prefixedNo, help: "Link Swift stdlib statically")
526526
public var shouldLinkStaticSwiftStdlib: Bool = false
527+
528+
/// Disables adding $ORIGIN/@loader_path to the rpath, useful when deploying
529+
@Flag(name: .customLong("disable-local-rpath"), help: "Disable adding $ORIGIN/@loader_path to the rpath by default")
530+
public var shouldDisableLocalRpath: Bool = false
527531
}
528532

529533
// MARK: - Extensions

Sources/CoreCommands/SwiftTool.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ public final class SwiftTool {
683683
architectures: options.build.architectures,
684684
workers: options.build.jobs ?? UInt32(ProcessInfo.processInfo.activeProcessorCount),
685685
shouldLinkStaticSwiftStdlib: options.linker.shouldLinkStaticSwiftStdlib,
686+
shouldDisableLocalRpath: options.linker.shouldDisableLocalRpath,
686687
canRenameEntrypointFunctionName: driverSupport.checkSupportedFrontendFlags(
687688
flags: ["entry-point-function-name"],
688689
toolchain: toolchain,

Sources/SPMBuildCore/BuildParameters.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ public struct BuildParameters: Encodable {
190190
/// If should link the Swift stdlib statically.
191191
public var shouldLinkStaticSwiftStdlib: Bool
192192

193+
/// Disables adding $ORIGIN/@loader_path to the rpath, useful when deploying
194+
public var shouldDisableLocalRpath: Bool
195+
193196
/// Which compiler sanitizers should be enabled
194197
public var sanitizers: EnabledSanitizers
195198

@@ -362,6 +365,7 @@ public struct BuildParameters: Encodable {
362365
architectures: [String]? = nil,
363366
workers: UInt32 = UInt32(ProcessInfo.processInfo.activeProcessorCount),
364367
shouldLinkStaticSwiftStdlib: Bool = false,
368+
shouldDisableLocalRpath: Bool = false,
365369
shouldEnableManifestCaching: Bool = false,
366370
canRenameEntrypointFunctionName: Bool = false,
367371
shouldCreateDylibForDynamicProducts: Bool = true,
@@ -424,6 +428,7 @@ public struct BuildParameters: Encodable {
424428
self.architectures = architectures
425429
self.workers = workers
426430
self.shouldLinkStaticSwiftStdlib = shouldLinkStaticSwiftStdlib
431+
self.shouldDisableLocalRpath = shouldDisableLocalRpath
427432
self.shouldEnableManifestCaching = shouldEnableManifestCaching
428433
self.shouldCreateDylibForDynamicProducts = shouldCreateDylibForDynamicProducts
429434
self.canRenameEntrypointFunctionName = canRenameEntrypointFunctionName
@@ -487,6 +492,7 @@ public struct BuildParameters: Encodable {
487492
architectures: nil,
488493
workers: self.workers,
489494
shouldLinkStaticSwiftStdlib: self.shouldLinkStaticSwiftStdlib,
495+
shouldDisableLocalRpath: self.shouldDisableLocalRpath,
490496
shouldEnableManifestCaching: self.shouldEnableManifestCaching,
491497
canRenameEntrypointFunctionName: self.canRenameEntrypointFunctionName,
492498
shouldCreateDylibForDynamicProducts: self.shouldCreateDylibForDynamicProducts,

Sources/swift-bootstrap/main.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
118118
case error
119119
}
120120

121+
/// Disables adding $ORIGIN/@loader_path to the rpath, useful when deploying
122+
@Flag(name: .customLong("disable-local-rpath"), help: "Disable adding $ORIGIN/@loader_path to the rpath by default")
123+
public var shouldDisableLocalRpath: Bool = false
124+
121125
private var buildSystem: BuildSystemProvider.Kind {
122126
#if os(macOS)
123127
// Force the Xcode build system if we want to build more than one arch.
@@ -188,7 +192,8 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
188192
buildFlags: self.buildFlags,
189193
manifestBuildFlags: self.manifestFlags,
190194
useIntegratedSwiftDriver: self.useIntegratedSwiftDriver,
191-
explicitTargetDependencyImportCheck: self.explicitTargetDependencyImportCheck
195+
explicitTargetDependencyImportCheck: self.explicitTargetDependencyImportCheck,
196+
shouldDisableLocalRpath: self.shouldDisableLocalRpath
192197
)
193198
} catch _ as Diagnostics {
194199
throw ExitCode.failure
@@ -232,7 +237,8 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
232237
buildFlags: BuildFlags,
233238
manifestBuildFlags: [String],
234239
useIntegratedSwiftDriver: Bool,
235-
explicitTargetDependencyImportCheck: TargetDependencyImportCheckingMode
240+
explicitTargetDependencyImportCheck: TargetDependencyImportCheckingMode,
241+
shouldDisableLocalRpath: Bool
236242
) throws {
237243
let buildSystem = try createBuildSystem(
238244
packagePath: packagePath,
@@ -244,6 +250,7 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
244250
manifestBuildFlags: manifestBuildFlags,
245251
useIntegratedSwiftDriver: useIntegratedSwiftDriver,
246252
explicitTargetDependencyImportCheck: explicitTargetDependencyImportCheck,
253+
shouldDisableLocalRpath: shouldDisableLocalRpath,
247254
logLevel: logLevel
248255
)
249256
try buildSystem.build(subset: .allExcludingTests)
@@ -259,6 +266,7 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
259266
manifestBuildFlags: [String],
260267
useIntegratedSwiftDriver: Bool,
261268
explicitTargetDependencyImportCheck: TargetDependencyImportCheckingMode,
269+
shouldDisableLocalRpath: Bool,
262270
logLevel: Basics.Diagnostic.Severity
263271
) throws -> BuildSystem {
264272

@@ -277,6 +285,7 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
277285
targetTriple: self.targetToolchain.targetTriple,
278286
flags: buildFlags,
279287
architectures: architectures,
288+
shouldDisableLocalRpath: shouldDisableLocalRpath,
280289
useIntegratedSwiftDriver: useIntegratedSwiftDriver,
281290
isXcodeBuildSystemEnabled: buildSystem == .xcode,
282291
explicitTargetDependencyImportCheckingMode: explicitTargetDependencyImportCheck == .error ? .error : .none,

Tests/BuildTests/BuildPlanTests.swift

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5021,4 +5021,87 @@ final class BuildPlanTests: XCTestCase {
50215021
XCTFail("expected a Swift target")
50225022
}
50235023
}
5024+
5025+
func testBasicSwiftPackageWithoutLocalRpath() throws {
5026+
let fs = InMemoryFileSystem(emptyFiles:
5027+
"/Pkg/Sources/exe/main.swift",
5028+
"/Pkg/Sources/lib/lib.swift"
5029+
)
5030+
5031+
let observability = ObservabilitySystem.makeForTesting()
5032+
let graph = try loadPackageGraph(
5033+
fileSystem: fs,
5034+
manifests: [
5035+
Manifest.createRootManifest(
5036+
displayName: "Pkg",
5037+
path: "/Pkg",
5038+
targets: [
5039+
TargetDescription(name: "exe", dependencies: ["lib"]),
5040+
TargetDescription(name: "lib", dependencies: []),
5041+
]),
5042+
],
5043+
observabilityScope: observability.topScope
5044+
)
5045+
XCTAssertNoDiagnostics(observability.diagnostics)
5046+
5047+
let result = try BuildPlanResult(plan: BuildPlan(
5048+
buildParameters: mockBuildParameters(shouldDisableLocalRpath: true),
5049+
graph: graph,
5050+
fileSystem: fs,
5051+
observabilityScope: observability.topScope
5052+
))
5053+
5054+
result.checkProductsCount(1)
5055+
result.checkTargetsCount(2)
5056+
5057+
let buildPath = result.plan.buildParameters.dataPath.appending(components: "debug")
5058+
5059+
#if os(macOS)
5060+
let linkArguments = [
5061+
result.plan.buildParameters.toolchain.swiftCompilerPath.pathString,
5062+
"-L", buildPath.pathString,
5063+
"-o", buildPath.appending(components: "exe").pathString,
5064+
"-module-name", "exe",
5065+
"-emit-executable",
5066+
"@\(buildPath.appending(components: "exe.product", "Objects.LinkFileList"))",
5067+
"-Xlinker", "-rpath", "-Xlinker", "/fake/path/lib/swift-5.5/macosx",
5068+
"-target", defaultTargetTriple,
5069+
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "exe.build", "exe.swiftmodule").pathString,
5070+
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "lib.swiftmodule").pathString,
5071+
"-g",
5072+
]
5073+
#elseif os(Windows)
5074+
let linkArguments = [
5075+
result.plan.buildParameters.toolchain.swiftCompilerPath.pathString,
5076+
"-L", buildPath.pathString,
5077+
"-o", buildPath.appending(components: "exe.exe").pathString,
5078+
"-module-name", "exe",
5079+
"-emit-executable",
5080+
"@\(buildPath.appending(components: "exe.product", "Objects.LinkFileList"))",
5081+
"-target", defaultTargetTriple,
5082+
"-g", "-use-ld=lld", "-Xlinker", "-debug:dwarf",
5083+
]
5084+
#else
5085+
let linkArguments = [
5086+
result.plan.buildParameters.toolchain.swiftCompilerPath.pathString,
5087+
"-L", buildPath.pathString,
5088+
"-o", buildPath.appending(components: "exe").pathString,
5089+
"-module-name", "exe",
5090+
"-emit-executable",
5091+
"@\(buildPath.appending(components: "exe.product", "Objects.LinkFileList"))",
5092+
"-target", defaultTargetTriple,
5093+
"-g"
5094+
]
5095+
#endif
5096+
5097+
XCTAssertEqual(try result.buildProduct(for: "exe").linkArguments(), linkArguments)
5098+
5099+
#if os(macOS)
5100+
testDiagnostics(observability.diagnostics) { result in
5101+
result.check(diagnostic: .contains("can be downloaded"), severity: .warning)
5102+
}
5103+
#else
5104+
XCTAssertNoDiagnostics(observability.diagnostics)
5105+
#endif
5106+
}
50245107
}

Tests/BuildTests/MockBuildTestHelper.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func mockBuildParameters(
7070
toolchain: PackageModel.Toolchain = MockToolchain(),
7171
flags: PackageModel.BuildFlags = PackageModel.BuildFlags(),
7272
shouldLinkStaticSwiftStdlib: Bool = false,
73+
shouldDisableLocalRpath: Bool = false,
7374
canRenameEntrypointFunctionName: Bool = false,
7475
targetTriple: Basics.Triple = hostTriple,
7576
indexStoreMode: BuildParameters.IndexStoreMode = .off,
@@ -87,6 +88,7 @@ func mockBuildParameters(
8788
pkgConfigDirectories: [],
8889
workers: 3,
8990
shouldLinkStaticSwiftStdlib: shouldLinkStaticSwiftStdlib,
91+
shouldDisableLocalRpath: shouldDisableLocalRpath,
9092
canRenameEntrypointFunctionName: canRenameEntrypointFunctionName,
9193
indexStoreMode: indexStoreMode,
9294
useExplicitModuleBuild: useExplicitModuleBuild,

Utilities/bootstrap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,9 @@ def get_swiftpm_flags(args):
765765
"--configuration", "release",
766766
])
767767

768+
if not '-macosx' in args.build_target and args.command == 'install':
769+
build_flags.append("--disable-local-rpath")
770+
768771
if args.verbose:
769772
build_flags.append("--verbose")
770773

0 commit comments

Comments
 (0)