Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode: Linking brand new framework to brand new app fails with "image not found"

I'm totally new to Xcode and Objective-C, but an experienced (web) programmer otherwise. I want to create an app that includes a self-made framework.

Now I've read quite a bit on it, I think I've got a reasonable grasp of how OS X resolves dependencies at runtime, and the role of @rpath, @executable_path and @loader_path.

I did the following to create the framework:

  1. Create new Cocoa Framework named Test.
  2. Set installation directory to "@rpath".
  3. Add "Test.h" to public headers.
  4. Click run.
  5. Right click on Test.framework under "Products", choose Show in Finder. It's a directory called "Test.framework" in the "Debug" directory of the project. It seems to have reasonable contents (Versions/A directory and symlinks to "Headers", "Resources" and the "Test" binary)

I did the following to create the app:

  1. Create new Cocoa app named "TestApp".
  2. Add test framework to project. Choose "Add files to project". Select "Test.framework" directory from "Release" directory of the Test framework project. "Copy items into destination group's folder" is checked Leave "Create groups for any added folders." on.
  3. Make sure framework files are copied to application bundle. Choose "Add Build Phase" -> "Add Copy Files" Drag Test.framework folder (or group?) from the sidebar into the Copy Files area.
  4. Add an extra "framework search path" named "@executable_path/../Frameworks"

When I choose run, I get the following warning during build:

Build target TestApp

Ld /Users/meryn/Library/Developer/Xcode/DerivedData/TestApp-ajwvknoonliuqqfaqxacxrmapyfz/Build/Products/Debug/TestApp.app/Contents/MacOS/TestApp normal x86_64 cd /Users/meryn/Work/test-app/TestApp setenv MACOSX_DEPLOYMENT_TARGET 10.8 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk -L/Users/meryn/Library/Developer/Xcode/DerivedData/TestApp-ajwvknoonliuqqfaqxacxrmapyfz/Build/Products/Debug -F/Users/meryn/Library/Developer/Xcode/DerivedData/TestApp-ajwvknoonliuqqfaqxacxrmapyfz/Build/Products/Debug -F/Users/meryn/Work/test-app/TestApp "-F@executable_path/../Frameworks" -filelist /Users/meryn/Library/Developer/Xcode/DerivedData/TestApp-ajwvknoonliuqqfaqxacxrmapyfz/Build/Intermediates/TestApp.build/Debug/TestApp.build/Objects-normal/x86_64/TestApp.LinkFileList -mmacosx-version-min=10.8 -fobjc-arc -fobjc-link-runtime -framework Cocoa -framework Test -o /Users/meryn/Library/Developer/Xcode/DerivedData/TestApp-ajwvknoonliuqqfaqxacxrmapyfz/Build/Products/Debug/TestApp.app/Contents/MacOS/TestApp

ld: warning: directory not found for option '-F@executable_path/../Frameworks'

I can imagine this warning is to be expected, as Ld may not know about "@executable_path" at all. Is this correct?

Subsequently, running the app fails with:

dyld: Library not loaded: @rpath/Test.framework/Versions/A/Test Referenced from: /Users/meryn/Library/Developer/Xcode/DerivedData/TestApp-ajwvknoonliuqqfaqxacxrmapyfz/Build/Products/Debug/TestApp.app/Contents/MacOS/TestApp Reason: image not found

The peculiar thing is that the TestApp.app package does contain a Frameworks directory, with the Test.framework directory inside. Given what I understand about how OS X would search for dependencies, I think the search path that I added should resolve fine.

This is on XCode 4.6, OS X 10.8.

otool -L TestApp gives

TestApp:

/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 19.0.0)

@rpath/Test.framework/Versions/A/Test (compatibility version 1.0.0, current version 1.0.0)

/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 945.11.0)

/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)

/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1187.33.0)

Is it ok to see "@rpath" unexpanded here?

What am I doing wrong?

like image 503
Myrne Stol Avatar asked Jan 14 '23 04:01

Myrne Stol


1 Answers

Since the library identifier is set to an @rpath-prefixed path, the application linking to the library needs to specify one or more -rpath options indicating what dyld should substitute the @rpath variable with when searching for the library at runtime. A typical value would be @loader_path/../Frameworks if you're copying your framework in to TestApp.app/Contents/Frameworks. You can set the value of the -rpath arguments using the LD_RUNPATH_SEARCH_PATHS ('Runpath Search Paths') configuration setting in Xcode on your TestApp target.

I can imagine this warning is to be expected, as Ld may not know about "@executable_path" at all. Is this correct?

It's not useful to add @executable_path/../Frameworks to Xcode's framework search paths. The framework search paths are a build-time concept of the static linker (ld), while the @executable_path variables are a runtime concept of the dynamic linker (dyld).

like image 115
bdash Avatar answered Jan 21 '23 12:01

bdash