如何在Xcode 4中使用dylib文件创建工作框架

use*_*020 18 macos xcode frameworks dylib

我在Xcode中创建了一个新的cocoa框架,删除了开头包含的所有库和文件,除了支持文件.

我有2个文件:

add.h

#ifndef add_add_h
#define add_add_h

void add(void);

#endif
Run Code Online (Sandbox Code Playgroud)

add.c
#include <stdio.h>
#include "add.h"

void add(void)
{
    printf("adfding");

}
Run Code Online (Sandbox Code Playgroud)

在构建阶段,我添加add.c来编译源代码,并添加add.h来编译头文件public.项目构建没有问题,但在框架中没有dylib文件,当我将框架拖放到另一个项目时,它说无法找到dylib文件.

dyld: Library not loaded: @rpath/add.framework/Versions/A/add 
  Referenced from: /Users/vjoukov/Desktop/Projects/test/build/Debug/test.app/Contents/MacOS/test
  Reason: image not found
Run Code Online (Sandbox Code Playgroud)

如何创建一个简单的框架并将dylib文件保存在其中?

NSG*_*God 62

我认为你误解了错误信息.

A .framework可用作动态库,但.dylib在.framework文件夹中不会有任何具有实际文件扩展名的Mach-O可加载对象文件.

有几个原因可能是您dyld在运行时从动态链接库加载器获取该错误消息.首先,您忘记在构建过程中将.frameworks复制到构建的应用程序包中.虽然可以将它们复制到应用程序包内的任何位置,但传统的位置是AppName.app/Contents/Frameworks/.如果尚未执行此操作,请选择"项目">"新建构建阶段">"新建复制文件构建阶段".将目标弹出窗口更改为框架,如下图所示.

在此输入图像描述

然后,您将框架的图标拖到文件夹中,以便在构建过程中复制它.

在此输入图像描述

在运行时无法找到框架的第二个也是更可能的原因是您没有为主可执行文件指定任何运行路径搜索路径.(这是必需的,因为正如我们从您的错误消息中看到的那样,您的框架是使用较新的@rpath/样式安装名称(@rpath/add.framework/Versions/A/add)而不是旧版本@executable_path/@loader_path/样式构建的.

如果将自定义框架复制到上述位置,则需要添加运行路径搜索路径条目@loader_path/../Frameworks,如下图所示:

在此输入图像描述

下面的摘录说明了如何在运行时找到动态库,请参阅以下联机帮助页dyld:

动态图书馆加载

与许多其他操作系统不同,Darwin没有通过其叶文件名来定位依赖的动态库.而是使用每个dylib的完整路径(例如 /usr/lib/libSystem.B.dylib).但有时候一条完整的道路并不合适; 例如,可能希望您的二进制文件可以安装在磁盘上的任何位置.为了支持这一点,有三个 @xxx/变量可以用作路径前缀.在运行时,dyld 将动态生成的路径替换为@xxx/前缀.

@executable_path/

此变量将替换为包含进程主可执行文件的目录的路径.这对于加载嵌入在.app目录中的dylib/framework很有用.如果主可执行文件位于/some/path/My.app/Contents/MacOS/My 并且框架dylib文件位于
/some/path/My.app/Contents/Frameworks/Foo.framework/Versions/A/Foo,则框架加载路径可以编码为 @executable_path/../Frameworks/Foo.framework/Versions/A/Foo ,并且.app目录可以在文件系统中移动,并且dyld仍然能够加载嵌入式框架.

@loader_path/

此变量将替换为包含mach-o二进制文件的目录的路径,该二进制文件包含使用的load命令 @loader_path.因此,在每个二进制文件中,@loader_path解析为不同的路径,而@executable_path始终解析为相同的路径.@loader_path如果插件的最终文件系统位置未知(因此无法使用绝对路径)或插件被多个应用程序使用(如果插件被多个应用程序使用),则作为嵌入在插件中的框架/ dylib的加载路径非常有用(所以 @executable_path 不能用).如果插件mach-o文件位于 /some/path/Myfilter.plugin/Contents/MacOS/Myfilter并且框架dylib文件位于 /some/path/Myfilter.plugin/Contents/Frameworks/Foo.framework/Versions/A/Foo,则框架加载路径可以编码为 @loader_path/../Frameworks/Foo.framework/Versions/A/Foo,并且 Myfilter.plugin目录可以在文件系统中移动并且dyld仍然能够加载嵌入式框架.

@rpath/

Dyld维护一个称为运行路径列表的当前路径堆栈.当 @rpath 遇到,如果发现其为被在运行路径列表中的每个路径,直到一个可加载dylib.运行路径堆栈是由LC_RPATH依赖链中的加载命令构建的,该命令导致当前的dylib加载.您可以LC_RPATH使用(1)-rpath选项向图像添加加载命令ld.您甚至可以添加一个LC_RPATH以...开头的加载命令路径, @loader_path/它将在运行路径堆栈上推送相对于包含该路径的图像的路径 LC_RPATH.@rpath当你有一个复杂的程序目录结构和dylib可以安装在任何地方,但保持它们的相对位置时,使用是最有用的.这种情况可以使用@loader_path,但是dylib的每个客户端都需要不同的加载路径,因为它在文件系统中的相对位置是不同的.使用 @rpath 引入了简化事物的间接级别.您在目录结构中选择一个位置作为锚点.然后每个dylib获得一个以@rpathand 开头的安装路径,并且是相对于锚点的dylib的路径.每个主要可执行文件都链接-rpath @loader_path/zzz,其中zzz是从可执行文件到锚点的路径.在运行时 dyld设置它将运行路径作为锚点,然后找到相对于锚点的每个dylib.

  • 哇!这是一个完整的答案,它也解决了我遇到的问题!谢谢!! (5认同)