【问题标题】:Including third party framework in Xcode project在 Xcode 项目中包含第三方框架
【发布时间】:2014-11-28 20:24:04
【问题描述】:

我很难将 TagLib 框架正确包含在 Xcode 6 中的 OS X Objective-C(++) 项目中。最终,我的目标是让框架与我的应用程序包一起分发,以便一切是完全独立的。由于我不确定我哪里出错了,让我从一开始就从我到目前为止所做的事情开始。

我从 GitHub 中获取了 TagLib,并使用 CMake 将其构建到了一个框架中。这些是我使用的构建选项:

cmake -DCMAKE_BUILD_TYPE=Release \
-DBUILD_FRAMEWORK=ON \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.10 \
-DCMAKE_OSX_ARCHITECTURES="x86_64"

这些是我认为的“可接受的最低限度”,它们来自 TagLib INSTALL 自述文件。在makemake install 之后,框架最终位于/Library/Frameworks。该框架在Versions 内有1.14.0 目录——这对于我的一个问题很重要(我认为)。

在 Xcode 中创建我的项目后,我做的下一件事是将框架添加到我的应用程序目标中的“链接框架和库”。然后,我为我的应用程序和测试目标添加了一个新的“复制文件”构建阶段,以将框架复制到包的框架目录中。从那里,我将/Library/Frameworks/tag.framework/Headers 添加到我的应用程序并测试目标的“用户标题搜索路径”。我做的最后一件事是将框架添加到我的测试目标的“Link Binary With Libraries”构建阶段。

此时,如果我不进行任何代码设计,我的项目就会构建。但是,如果我尝试运行应用程序或测试,我会收到此错误(名称已从路径中删除):

dyld: Library not loaded: /usr/local/lib/tag.framework/Versions/1.14.0/tag
Referenced from: /Users/.../Library/Developer/.../Build/Products/Debug...
Reason: image not found

dyld 在那里找不到框架是完全有道理的,因为它没有安装在那里。但为什么它首先要在那里寻找呢?我的应用目标的“运行时搜索路径”是@executable_path/../Frameworks,我的测试目标包括@loader_path/../Frameworks

现在,如果我尝试对我的项目进行代码设计,我什至无法构建它。我为“Signing”选择了“Mac App Store”,为“Team”选择了我的个人资料,并为我的“Copy Files”构建阶段重新选中了“Code Sign On Copy”框,然后 codesign 将其吐回:

/Users/.../Library/Developer/Xcode/DerivedData/.../Build/Products/Debug/.../Contents/Frameworks/tag.framework/Versions/A: No such file or directory
Command /usr/bin/codesign failed with exit code 1

同样,这条消息非常有意义,因为Versions 中没有A 目录——只有1.14.0Current 符号链接。但是它为什么要找A呢?

所以,我的问题最普遍的形式是,我如何正确地将这个框架包含到 Xcode 项目中,以便我可以 1) 没有外部依赖项(即,框架在包中)和 2) 有它的代码设计?我的过程是我在 SO 和 Apple Developer 网站上阅读的内容的集合,但我完全不确定它是否接近正确。我见过的唯一其他我没有尝试过的东西是使用“install_name_tool”和“otool”,但我不确定我需要更改什么或使用这两个工具中的哪一个。

非常感谢任何帮助或建议!

【问题讨论】:

    标签: objective-c xcode macos taglib codesign


    【解决方案1】:

    这是一个写得很好的问题。我在寻找我的问题的答案时遇到了它,这基本上是一样的。我想出了我的,并认为你在正确的轨道上。

    您确实需要修复框架的结构。不知道为什么构建不同,但基本上, 1.14.0 目录应该是 A 而不是 Current 应该是它的符号链接。这就是我所做的,并且处理了那部分。其他人通过删除 Current 符号链接并将 1.14.0 目录移动到 Current 来绕过它。坦率地说,我不知道为什么签名工具不去签署 Current,遵循符号链接,然后就可以工作了。我确实注意到在 Build Settings->Packaging 下有一个框架版本的构建设置设置为 A - 也许它可以更改为 Current 或 1.14.0?我将 1.14.0 移至 A 并删除并重新制作了符号链接或 Current->A(如果在框架/版本目录内,则 ln -s A Current)。

    在这一点上,我认为代码签名将适用于您,并且您将在运行时回到您的其他问题。那是因为框架安装路径在构建时没有正确设置。有不同的选项,但最灵活的是更改框架的构建以使用@rpath 作为安装位置,或者像我使用 install_name_tool 一样在事后修复它。例如,如果你 CD 到包含 tag.framework 包的目录,

    install_name_tool -id @rpath/tag.framework/Versions/A/tag tag.framework/Versions/A/tag 
    

    如果您要在构建之间更改这些内容,请确保在构建之前进行清理,除非您确定已设置了对框架的依赖项。 祝你好运。这对我来说也很烦人。

    标签库也应该更新他们的构建过程,我怀疑,虽然我从 Apple 阅读框架文档的方式,我认为目录名称 A、B 等只是示例,而不是固定规则,并且真正的规则是 Current 是一个符号链接,在指定位置的指定事物之外不允许有多余的东西。

    帮助我走过我的流浪之路的链接: https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html http://blog.gmane.org/gmane.comp.kde.devel.taglib/month=20081001/page=1 (以及上面的 mikeash 和 driben 链接!-我目前不能发布超过 2 个链接)

    【讨论】: