How do I create a working framework with dylib files in Xcode 4

≯℡__Kan透↙ 提交于 2019-12-02 15:58:10

I think you're misunderstanding the error message.

A .framework works as a dynamic library, but there won't be any Mach-O loadable object file with an actual .dylib filename extension inside the .framework folder.

There are a couple of reasons you might be getting that error message from dyld, the dynamic link library loader, at runtime. The first is that you forgot to copy the .frameworks into the built application bundle during the build process. While they can be copied to about any location inside the app bundle, the traditional place is in AppName.app/Contents/Frameworks/. If you haven't done so already, choose Project > New Build Phase > New Copy Files Build Phase. Change the Destination popup to Frameworks like in the image below.

You'll then drag the icon of the framework into the folder so that it's copied during the build process.

The second and more likely reason the framework can't be found at runtime is that you haven't specified any runpath search paths for your main executable. (This is needed, because, as we saw from your error message, your framework was built using the newer @rpath/ style install name (@rpath/add.framework/Versions/A/add) rather than the older @executable_path/ or @loader_path/ styles).

Provided you copy the custom frameworks to the location mentioned above, you'd add a runpath search path entry of @loader_path/../Frameworks, like shown in the image below:

The following excerpt that explains how dynamic libraries are found at runtime is from the manpage of dyld:

DYNAMIC LIBRARY LOADING

Unlike many other operating systems, Darwin does not locate dependent dynamic libraries via their leaf file name. Instead the full path to each dylib is used (e.g. /usr/lib/libSystem.B.dylib). But there are times when a full path is not appropriate; for instance, may want your binaries to be installable in anywhere on the disk. To support that, there are three @xxx/ variables that can be used as a path prefix. At runtime dyld substitutes a dynamically generated path for the @xxx/ prefix.

@executable_path/

This variable is replaced with the path to the directory containing the main executable for the process. This is useful for loading dylibs/frameworks embedded in a .app directory. If the main executable file is at /some/path/My.app/Contents/MacOS/My and a framework dylib file is at
/some/path/My.app/Contents/Frameworks/Foo.framework/Versions/A/Foo, then the framework load path could be encoded as @executable_path/../Frameworks/Foo.framework/Versions/A/Foo and the .app directory could be moved around in the file system and dyld will still be able to load the embedded framework.

@loader_path/

This variable is replaced with the path to the directory containing the mach-o binary which contains the load command using @loader_path. Thus, in every binary, @loader_path resolves to a different path, whereas @executable_path always resolves to the same path. @loader_path is useful as the load path for a framework/dylib embedded in a plug-in, if the final file system location of the plugin-in unknown (so absolute paths cannot be used) or if the plug-in is used by multiple applications (so @executable_path cannot be used). If the plug-in mach-o file is at /some/path/Myfilter.plugin/Contents/MacOS/Myfilter and a framework dylib file is at /some/path/Myfilter.plugin/Contents/Frameworks/Foo.framework/Versions/A/Foo, then the framework load path could be encoded as @loader_path/../Frameworks/Foo.framework/Versions/A/Foo and the Myfilter.plugin directory could be moved around in the file system and dyld will still be able to load the embedded framework.

@rpath/

Dyld maintains a current stack of paths called the run path list. When @rpath is encountered it is substituted with each path in the run path list until a loadable dylib if found. The run path stack is built from the LC_RPATH load commands in the depencency chain that lead to the current dylib load. You can add an LC_RPATH load command to an image with the -rpath option to ld(1). You can even add a LC_RPATH load command path that starts with @loader_path/, and it will push a path on the run path stack that relative to the image containing the LC_RPATH. The use of @rpath is most useful when you have a complex directory structure of programs and dylibs which can be installed anywhere, but keep their relative positions. This scenario could be implemented using @loader_path, but every client of a dylib could need a different load path because its relative position in the file system is different. The use of @rpath introduces a level of indirection that simplies things. You pick a location in your directory structure as an anchor point. Each dylib then gets an install path that starts with @rpath and is the path to the dylib relative to the anchor point. Each main executable is linked with -rpath @loader_path/zzz, where zzz is the path from the executable to the anchor point. At runtime dyld sets it run path to be the anchor point, then each dylib is found relative to the anchor point.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!