【问题标题】:How do I create a working framework with dylib files in Xcode 4如何在 Xcode 4 中使用 dylib 文件创建工作框架
【发布时间】:2011-11-25 15:24:12
【问题描述】:

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

我有 2 个文件:

add.h

#ifndef add_add_h
#define add_add_h

void add(void);

#endif

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

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

}

在构建阶段我添加 add.c 来编译源代码和 add.h 来编译公共头文件。项目构建没有问题,但在框架中没有 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

如何制作一个简单的框架并在其中保存 dylib 文件?

【问题讨论】:

    标签: xcode macos frameworks dylib


    【解决方案1】:

    我认为您误解了错误消息。

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

    您可能会在运行时从动态链接库加载器dyld 收到该错误消息,原因有几个。第一个是您在构建过程中忘记将 .frameworks 复制到构建的应用程序包中。虽然它们可以复制到应用程序包内的任何位置,但传统的位置是在 AppName.app/Contents/Frameworks/ 中。如果您还没有这样做,请选择 Project > New Build Phase > New Copy Files Build Phase。将 Destination 弹出窗口更改为 Frameworks,如下图所示。

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

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

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

    以下解释如何在运行时找到动态库的摘录来自dyld 的联机帮助页:

    动态库加载

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

    @executable_path/

    这个变量被替换为目录的路径 包含进程的主要可执行文件。这对 加载嵌入在 .app 目录中的 dylibs/frameworks。如果 主可执行文件位于/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 二进制文件,其中包含使用的加载命令 @loader_path。因此,在每个二进制文件中,@loader_path 解析为 不同的路径,而 @executable_path 总是解析为 相同的路径。 @loader_path 可用作 framework/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/FooMyfilter.plugin 目录可以是 在文件系统中移动,dyld 仍然可以 加载嵌入式框架。

    @rpath/

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

    【讨论】:

    • 哇!这是一个完整的答案,它也解决了我遇到的一个问题!谢谢!!
    • 非常彻底和完整的答案...干得好!
    • 虽然这个答案非常完整 - 它主要涵盖与其框架(或其他dylib)的可执行(App)关系。我需要从几个 .dylibs(应该嵌入到该框架中)构建一个框架,并且我的可执行 barfs 对嵌入 dylibs 中所有符号的链接错误。我正在尝试了解如何从几个 dylib 中构建一个框架——但似乎没有人对此写过任何东西。
    • @NSGod,在这种情况下你会怎么做:stackoverflow.com/questions/40318465/…?谢谢。
    猜你喜欢
    • 2011-11-27
    • 1970-01-01
    • 2010-09-16
    • 2015-01-16
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    • 2013-09-27
    • 1970-01-01
    相关资源
    最近更新 更多