Skip to content
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

[SR-6508] rpath order is inconsistent between Darwin and Linux #49058

Closed
kevints mannequin opened this issue Nov 30, 2017 · 5 comments
Closed

[SR-6508] rpath order is inconsistent between Darwin and Linux #49058

kevints mannequin opened this issue Nov 30, 2017 · 5 comments

Comments

@kevints
Copy link
Mannequin

@kevints kevints mannequin commented Nov 30, 2017

Previous ID SR-6508
Radar rdar://problem/35827397
Original Reporter @kevints
Type Bug
Status Closed
Resolution Done
Environment

Swift 4.0.2

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, Driver, StarterBug
Assignee @keith
Priority Medium

md5: 2e78181413954a0e98d1e8a39b2b1e69

Issue Description:

On Darwin, the swift compiler takes care to place its own rpath (the location of the swift standard library) after any user-specified rpaths.

static void
addLinkRuntimeLibForDarwin(const ArgList &Args, ArgStringList &Arguments,
StringRef DarwinLibName, bool AddRPath,
const ToolChain &TC) {
SmallString<128> ClangLibraryPath;
getClangLibraryPathOnDarwin(ClangLibraryPath, Args, TC);
SmallString<128> P(ClangLibraryPath);
llvm::sys::path::append(P, DarwinLibName);
Arguments.push_back(Args.MakeArgString(P));
// Adding the rpaths might negatively interact when other rpaths are involved,
// so we should make sure we add the rpaths last, after all user-specified
// rpaths. This is currently true from this place, but we need to be
// careful if this function is ever called before user's rpaths are emitted.
if (AddRPath) {
assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library");
// Add @executable_path to rpath to support having the dylib copied with
// the executable.
Arguments.push_back("-rpath");
Arguments.push_back("@executable_path");
// Add the path to the resource dir to rpath to support using the dylib
// from the default location without copying.
Arguments.push_back("-rpath");
Arguments.push_back(Args.MakeArgString(ClangLibraryPath));
}
}

On Linux this is not the case

To reproduce, start from a new executable package (swift package init --type executable) (called test), and build with

swift build -Xlinker -rpath -Xlinker /usr/local/lib

On macOS this produces a binary with a runtime library search path containing 2 entries, as follows:

  • /usr/local/lib (the user-provided search path)

  • the location of the swift standard library

To observe this use otool -l as follows:

$ swift build -Xlinker -rpath -Xlinker /usr/local/lib
Linking ./.build/x86_64-apple-macosx10.10/debug/test
$ otool -l ./.build/debug/test
...
Load command 18
          cmd LC_RPATH
      cmdsize 32
         path /usr/local/lib (offset 12)
Load command 19
          cmd LC_RPATH
      cmdsize 112
         path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx (offset 12)
...

On Linux this same command produces a binary whose runtime library search path has 3 entries, as follows:

  • the location of the swift standard library

  • /usr/local/lib (the user-provided search path)

  • $ORIGIN, a symbol indicating the directory containing the binary (similar to Darwin's @executable_path).

This can be observed with the readelf command:

$ readelf -d ./.build/debug/test
...
 0x000000000000001d (RUNPATH)            Library runpath: [/usr/lib/swift/linux:/usr/local/lib:$ORIGIN]

It seems strange that the Linux version gives a different order than the Darwin one, I would expect the order to be consistent across platforms. Furthermore, I think the Darwin order is the correct one as it allows each layer to override a lower one (a swiftPM user can override swiftPM's authors which in turn can override swiftc). It's possible that on Darwin, SwiftPM should also insert @executable_path between user-specified search paths and compiler-specified ones.

@swift-ci
Copy link
Collaborator

@swift-ci swift-ci commented Dec 4, 2017

Comment by Gregor Milos (Grzegorz Miłoś) (JIRA)

@swift-ci create

@keith
Copy link
Collaborator

@keith keith commented Jul 26, 2018

Submitted #18266 as a possible solution. @belkadan Ankit mentioned you might have an opinion on this change // gmilos (JIRA User)

@keith
Copy link
Collaborator

@keith keith commented Jul 26, 2018

> It's possible that on Darwin, SwiftPM should also insert @executable_path between user-specified search paths and compiler-specified ones.

Per a conversation in the swiftpm slack, this should be handled by more generic fixes to the paths necessary for custom dylibs, which aren't handled well right now and end up being the absolute path to the built product.

@keith
Copy link
Collaborator

@keith keith commented Jul 31, 2018

So this has been "fixed" in the linked PR, but maybe not in the way this ticket had hoped. The custom rpaths defined by -Xlinker are now last in the list, meaning they will no longer take precedence to the system ones on Darwin or Linux. This was the intention of these flags, which is why we changed this, but the hope from this original ticket was the ability to override the default rpath, which wasn't possible with Darwin originally, and now won't be possible with Linux as well. There was a recommendation to add a flag to disable the default rpaths, which I think would be a reasonable solution / follow up to this change.

@keith
Copy link
Collaborator

@keith keith commented Aug 6, 2018

This change is merged so I'm going to close this. Like I said above there might be another ticket worth creating out of this to allow users to disable the default rpaths.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants