@loader_path only works in Xcode
@loader_path only works in Xcode
- Subject: @loader_path only works in Xcode
- From: Jerry Krinock <email@hidden>
- Date: Fri, 17 Aug 2012 19:00:01 -0700
SUMMARY
In the Sparkle framework [1], the Install Name uses the token @loader_path to smartly resolve relative paths. My app's helper tool links to a private framework which in turn links to Sparkle. But the link to Sparkle fails, unless the tool is run within Xcode 4.
BACKGROUND
I've read the documentation, and Mike Ash's Friday Q&A on this subject [2] several times.
I understand that, during linking, the "Install Name" in a dynamic library tells a "loader" ("linker") of the library where to find the library at runtime. The @executable_path token was introduced so that Install Name could contain a relative path, which is helpful when a dynamic library is shipped in an application bundle, for example. But @executable_path does not work for nested links such as this,
app -> dylib1 -> dylib2
because at runtime dylib1 will look for dylib2 relative to app (the executable) instead of relative to itself. To solve this problem, Apple later introduced the @loader_path token, which resolves to the immediate parent, instead of traveling up the hierarchy to the executable.
DETAILS
My app's bundle looks like this…
Contents
MacOS
MainAppExecutable
Frameworks
MainFramework.framework
Sparkle.framework
...
Helpers
Helper1
...
...
MainAppExecutable is linked to MainFramework which in turn links to Sparkle.framework. In Sparkle.framework, the Installation Directory is set to @loader_path/../Frameworks, and the Dynamic Library Install Name resolves to @loader_path/../Frameworks/Sparkle.framework/Versions/A/Sparkle. Main app works OK.
Helper1 also links to MainFramework. When I set the Scheme in Xcode to run Helper1 (and set its executable to the copy of Helper1 in the application bundle), and "Run" in Xcode, it works OK too.
But when I try to run Helper1 outside of Xcode, it crashes on launch because MainFramework.framework cannot find Sparkle.framework. It crashes whether Helper1 is invoked by launchd (which is the way it works in real life) or manually, from the command line, like this…
Air1:Contents jk$ pwd
/Users/jk/Library/Developer/Xcode/DerivedData/MainApp-hkrnkbihzhcgkngzhdqroeilxfyd/Build/Products/Debug/MainApp.app/Contents
Air1:Contents jk$ Helpers/Helper1
dyld: Library not loaded: @loader_path/../Frameworks/Sparkle.framework/Versions/A/Sparkle
Referenced from: /Users/jk/Library/Developer/Xcode/DerivedData/MainApp-hkrnkbihzhcgkngzhdqroeilxfyd/Build/Products/Debug/MainApp.app/Contents/Frameworks/MainFramework.framework/Versions/A/MainFramework
Reason: image not found
Trace/BPT trap: 5
Why? The loader is MainFramework; therefore @loader_path is /path/toContents/Frameworks. The Install Name should therefore resolve by traversing "/.." to the parent directory, which is /path/to/Contents, then back down into Frameworks/Sparkle.framework, etc., resulting in /path/to/Contents/Frameworks/Sparkle.framework/Versions/A/Sparkle, as required.
Thank you,
Jerry Krinock
MORE DETAILS
• I verified the Installation Directory of Sparkle.framework build…
Air1:Contents jk$ otool -D Frameworks/Sparkle.framework/Versions/A/Sparkle
Frameworks/Sparkle.framework/Versions/A/Sparkle:
@loader_path/../Frameworks/Sparkle.framework/Versions/A/Sparkle
• Ironically, to work around the problem in this case, in Sparkle framework's Build Settings I changed @loader_path to the old-fashioned @executable_path, and re-build. Result: Helper1 works OK whether it is launched within Xcode or without. Tracing the paths, this makes sense
• The lipo tool assures me that Sparkle contains both i386 and x86_64 architectures. It does not "Build Active Architecture Only".
• Helper1's "Link Binary With Libraries" Build Phase contains only one library, MainFramework.
REFERENCES
[1] http://sparkle.andymatuschak.org
[2] http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden