• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag
 

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
@loader_path only works in Xcode
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

@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


  • Follow-Ups:
    • Re: @loader_path only works in Xcode
      • From: Jeff Johnson <email@hidden>
  • Prev by Date: Re: Deprecated warnings on Intel 10.4.11, not on PPC 10.4.11
  • Next by Date: Re: @loader_path only works in Xcode
  • Previous by thread: Re: How can I programmatically add build files to Xcode4?
  • Next by thread: Re: @loader_path only works in Xcode
  • Index(es):
    • Date
    • Thread