Skip to content

Add an rpath flag to disable the default of looking in the local directory for shared libraries #6947

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 1 commit into from
Oct 10, 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
14 changes: 8 additions & 6 deletions Sources/Build/BuildDescription/ProductBuildDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,14 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
}

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

Expand Down
4 changes: 4 additions & 0 deletions Sources/CoreCommands/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,10 @@ public struct LinkerOptions: ParsableArguments {
/// If should link the Swift stdlib statically.
@Flag(name: .customLong("static-swift-stdlib"), inversion: .prefixedNo, help: "Link Swift stdlib statically")
public var shouldLinkStaticSwiftStdlib: Bool = false

/// Disables adding $ORIGIN/@loader_path to the rpath, useful when deploying
@Flag(name: .customLong("disable-local-rpath"), help: "Disable adding $ORIGIN/@loader_path to the rpath by default")
public var shouldDisableLocalRpath: Bool = false
Copy link
Member Author

Choose a reason for hiding this comment

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

I don't care what the flag name is, feel free to suggest another.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would call it "origin" instead of "local"

Copy link
Member Author

Choose a reason for hiding this comment

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

I considered that originally but used this broader term when I disabled the Darwin @loader_path too. Do you want me to keep that disabled for Darwin and change this flag and variable name to origin? I have no preference on these two aspects of this pull.

}

// MARK: - Extensions
Expand Down
1 change: 1 addition & 0 deletions Sources/CoreCommands/SwiftTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,7 @@ public final class SwiftTool {
architectures: options.build.architectures,
workers: options.build.jobs ?? UInt32(ProcessInfo.processInfo.activeProcessorCount),
shouldLinkStaticSwiftStdlib: options.linker.shouldLinkStaticSwiftStdlib,
shouldDisableLocalRpath: options.linker.shouldDisableLocalRpath,
canRenameEntrypointFunctionName: driverSupport.checkSupportedFrontendFlags(
flags: ["entry-point-function-name"],
toolchain: toolchain,
Expand Down
6 changes: 6 additions & 0 deletions Sources/SPMBuildCore/BuildParameters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ public struct BuildParameters: Encodable {
/// If should link the Swift stdlib statically.
public var shouldLinkStaticSwiftStdlib: Bool

/// Disables adding $ORIGIN/@loader_path to the rpath, useful when deploying
public var shouldDisableLocalRpath: Bool

/// Which compiler sanitizers should be enabled
public var sanitizers: EnabledSanitizers

Expand Down Expand Up @@ -362,6 +365,7 @@ public struct BuildParameters: Encodable {
architectures: [String]? = nil,
workers: UInt32 = UInt32(ProcessInfo.processInfo.activeProcessorCount),
shouldLinkStaticSwiftStdlib: Bool = false,
shouldDisableLocalRpath: Bool = false,
shouldEnableManifestCaching: Bool = false,
canRenameEntrypointFunctionName: Bool = false,
shouldCreateDylibForDynamicProducts: Bool = true,
Expand Down Expand Up @@ -424,6 +428,7 @@ public struct BuildParameters: Encodable {
self.architectures = architectures
self.workers = workers
self.shouldLinkStaticSwiftStdlib = shouldLinkStaticSwiftStdlib
self.shouldDisableLocalRpath = shouldDisableLocalRpath
self.shouldEnableManifestCaching = shouldEnableManifestCaching
self.shouldCreateDylibForDynamicProducts = shouldCreateDylibForDynamicProducts
self.canRenameEntrypointFunctionName = canRenameEntrypointFunctionName
Expand Down Expand Up @@ -487,6 +492,7 @@ public struct BuildParameters: Encodable {
architectures: nil,
workers: self.workers,
shouldLinkStaticSwiftStdlib: self.shouldLinkStaticSwiftStdlib,
shouldDisableLocalRpath: self.shouldDisableLocalRpath,
shouldEnableManifestCaching: self.shouldEnableManifestCaching,
canRenameEntrypointFunctionName: self.canRenameEntrypointFunctionName,
shouldCreateDylibForDynamicProducts: self.shouldCreateDylibForDynamicProducts,
Expand Down
13 changes: 11 additions & 2 deletions Sources/swift-bootstrap/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
case error
}

/// Disables adding $ORIGIN/@loader_path to the rpath, useful when deploying
@Flag(name: .customLong("disable-local-rpath"), help: "Disable adding $ORIGIN/@loader_path to the rpath by default")
public var shouldDisableLocalRpath: Bool = false

private var buildSystem: BuildSystemProvider.Kind {
#if os(macOS)
// Force the Xcode build system if we want to build more than one arch.
Expand Down Expand Up @@ -188,7 +192,8 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
buildFlags: self.buildFlags,
manifestBuildFlags: self.manifestFlags,
useIntegratedSwiftDriver: self.useIntegratedSwiftDriver,
explicitTargetDependencyImportCheck: self.explicitTargetDependencyImportCheck
explicitTargetDependencyImportCheck: self.explicitTargetDependencyImportCheck,
shouldDisableLocalRpath: self.shouldDisableLocalRpath
)
} catch _ as Diagnostics {
throw ExitCode.failure
Expand Down Expand Up @@ -232,7 +237,8 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
buildFlags: BuildFlags,
manifestBuildFlags: [String],
useIntegratedSwiftDriver: Bool,
explicitTargetDependencyImportCheck: TargetDependencyImportCheckingMode
explicitTargetDependencyImportCheck: TargetDependencyImportCheckingMode,
shouldDisableLocalRpath: Bool
) throws {
let buildSystem = try createBuildSystem(
packagePath: packagePath,
Expand All @@ -244,6 +250,7 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
manifestBuildFlags: manifestBuildFlags,
useIntegratedSwiftDriver: useIntegratedSwiftDriver,
explicitTargetDependencyImportCheck: explicitTargetDependencyImportCheck,
shouldDisableLocalRpath: shouldDisableLocalRpath,
logLevel: logLevel
)
try buildSystem.build(subset: .allExcludingTests)
Expand All @@ -259,6 +266,7 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
manifestBuildFlags: [String],
useIntegratedSwiftDriver: Bool,
explicitTargetDependencyImportCheck: TargetDependencyImportCheckingMode,
shouldDisableLocalRpath: Bool,
logLevel: Basics.Diagnostic.Severity
) throws -> BuildSystem {

Expand All @@ -277,6 +285,7 @@ struct SwiftBootstrapBuildTool: ParsableCommand {
targetTriple: self.targetToolchain.targetTriple,
flags: buildFlags,
architectures: architectures,
shouldDisableLocalRpath: shouldDisableLocalRpath,
useIntegratedSwiftDriver: useIntegratedSwiftDriver,
isXcodeBuildSystemEnabled: buildSystem == .xcode,
explicitTargetDependencyImportCheckingMode: explicitTargetDependencyImportCheck == .error ? .error : .none,
Expand Down
76 changes: 76 additions & 0 deletions Tests/BuildTests/BuildPlanTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5021,4 +5021,80 @@ final class BuildPlanTests: XCTestCase {
XCTFail("expected a Swift target")
}
}

func testBasicSwiftPackageWithoutLocalRpath() throws {
Copy link
Member Author

Choose a reason for hiding this comment

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

This test is a copy and paste of testBasicSwiftPackage() above, with the rpath disabled and a few checks removed.

let fs = InMemoryFileSystem(emptyFiles:
"/Pkg/Sources/exe/main.swift",
"/Pkg/Sources/lib/lib.swift"
)

let observability = ObservabilitySystem.makeForTesting()
let graph = try loadPackageGraph(
fileSystem: fs,
manifests: [
Manifest.createRootManifest(
displayName: "Pkg",
path: "/Pkg",
targets: [
TargetDescription(name: "exe", dependencies: ["lib"]),
TargetDescription(name: "lib", dependencies: []),
]),
],
observabilityScope: observability.topScope
)
XCTAssertNoDiagnostics(observability.diagnostics)

let result = try BuildPlanResult(plan: BuildPlan(
buildParameters: mockBuildParameters(shouldDisableLocalRpath: true),
graph: graph,
fileSystem: fs,
observabilityScope: observability.topScope
))

result.checkProductsCount(1)
result.checkTargetsCount(2)

let buildPath = result.plan.buildParameters.dataPath.appending(components: "debug")

#if os(macOS)
let linkArguments = [
result.plan.buildParameters.toolchain.swiftCompilerPath.pathString,
"-L", buildPath.pathString,
"-o", buildPath.appending(components: "exe").pathString,
"-module-name", "exe",
"-emit-executable",
"@\(buildPath.appending(components: "exe.product", "Objects.LinkFileList"))",
"-Xlinker", "-rpath", "-Xlinker", "/fake/path/lib/swift-5.5/macosx",
"-target", defaultTargetTriple,
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "exe.build", "exe.swiftmodule").pathString,
"-Xlinker", "-add_ast_path", "-Xlinker", buildPath.appending(components: "lib.swiftmodule").pathString,
"-g",
]
#elseif os(Windows)
let linkArguments = [
result.plan.buildParameters.toolchain.swiftCompilerPath.pathString,
"-L", buildPath.pathString,
"-o", buildPath.appending(components: "exe.exe").pathString,
"-module-name", "exe",
"-emit-executable",
"@\(buildPath.appending(components: "exe.product", "Objects.LinkFileList"))",
"-target", defaultTargetTriple,
"-g", "-use-ld=lld", "-Xlinker", "-debug:dwarf",
]
#else
let linkArguments = [
result.plan.buildParameters.toolchain.swiftCompilerPath.pathString,
"-L", buildPath.pathString,
"-o", buildPath.appending(components: "exe").pathString,
"-module-name", "exe",
"-emit-executable",
"@\(buildPath.appending(components: "exe.product", "Objects.LinkFileList"))",
"-target", defaultTargetTriple,
"-g"
]
#endif

XCTAssertEqual(try result.buildProduct(for: "exe").linkArguments(), linkArguments)
XCTAssertNoDiagnostics(observability.diagnostics)
}
}
2 changes: 2 additions & 0 deletions Tests/BuildTests/MockBuildTestHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func mockBuildParameters(
toolchain: PackageModel.Toolchain = MockToolchain(),
flags: PackageModel.BuildFlags = PackageModel.BuildFlags(),
shouldLinkStaticSwiftStdlib: Bool = false,
shouldDisableLocalRpath: Bool = false,
canRenameEntrypointFunctionName: Bool = false,
targetTriple: Basics.Triple = hostTriple,
indexStoreMode: BuildParameters.IndexStoreMode = .off,
Expand All @@ -88,6 +89,7 @@ func mockBuildParameters(
pkgConfigDirectories: [],
workers: 3,
shouldLinkStaticSwiftStdlib: shouldLinkStaticSwiftStdlib,
shouldDisableLocalRpath: shouldDisableLocalRpath,
canRenameEntrypointFunctionName: canRenameEntrypointFunctionName,
indexStoreMode: indexStoreMode,
useExplicitModuleBuild: useExplicitModuleBuild,
Expand Down
3 changes: 3 additions & 0 deletions Utilities/bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,9 @@ def get_swiftpm_flags(args):
"--configuration", "release",
])

if not '-macosx' in args.build_target and args.command == 'install':
build_flags.append("--disable-local-rpath")

if args.verbose:
build_flags.append("--verbose")

Expand Down