我们什么时候应该在 Xcode 中使用 "embedded binaries" 而不是 "Linked Frameworks"?

When should we use "embedded binaries" rather than "Linked Frameworks" in Xcode?

关于 Link Binary with libraries VS Embed Frameworks 中描述的这两个选项之间的区别有一个很好的问题。

似乎我们可以选择同时使用它们,只是想知道在哪种情况下我们应该更好地使用嵌入式二进制文件,或者而不是链接框架?

有没有具体的例子可以更清楚地解决这个问题?谢谢

您 link 编辑的问题引用了 "Link Binary With Libraries" 功能,这与嵌入式二进制文件有些不同。

"Link Binary With Libraries" 表示您对 linkage 的期望:无论二进制文件是静态库、动态库还是框架,它都将是 link在编译后 link 时编辑到你的 object 代码。

当您想到静态库 linkage 时,发生的事情很清楚:linker copy 库中的代码(例如 libFoo.a) 到您的输出二进制文件中。您的输出文件变大了,但不需要在 运行 时解决任何外部依赖关系。您的程序 运行(相对于静态库)所需的一切在构建后都存在。

使用动态库(.dylib 或 system-supplied 框架),期望您 link 反对的库将出现在系统的 dynamic-library 加载器中的某个位置运行 程序时的路径。这样你就没有将所有第三方外部库复制到你的二进制文件中的开销,并且计算机上所有也 link 到该库的不同程序都能够找到它,这样可以节省最少的磁盘空间space,但也可能是内存 space,具体取决于系统缓存库的方式和位置。

框架很像动态库,但可以在其目录结构中包含资源(图像、音频、其他框架等)。在这种情况下,一个简单的 static-library 或 .dylib 文件不会削减它,因此您可能必须 link 到一个框架,这样 it 才能找到它需要的东西到 运行 正确。

当你 link 到 third-party 框架(比如你从 github 下载并自己构建的东西)时,它可能不会出现在你打算 运行 上。在这种情况下,您不仅要 link 到框架,还要使用 "Copy Frameworks" 阶段将它嵌入到您的应用程序包中。当你的程序 运行s 时,runtime-linker(又名解析器)除了系统加载程序路径外,还会在你的包中查找,找到嵌入式框架,然后 link 它这样你的应用程序就会拥有 运行.

所需的代码

最后,"embedded binary" 是一个可执行文件,您通过 Copy-Files 阶段将它们嵌入到您的应用程序包中,并且您自己执行,也许通过调用 popen() 或类似的。嵌入的二进制文件可能会被您的程序调用,但它不会被 link 编辑。它是一个完全外部的实体(就像 /bin 目录中的程序)。

实际上,对于 system-supplied 库和框架,您将 link 反对它们,这就是您需要做的全部。

如果您需要 link 您构建的不需要任何嵌入式资源的库(即不需要框架存在),那么您可以 link 针对静态图书馆。如果您发现您的程序中有多个模块想要使用相同的库代码,那么将其转换为框架或动态库并 link 反对它可以节省 space 并且可能很方便(特别是如果内存使用是一个问题)。

最后,框架不仅可以包含资源,还可以包含 header and/or 许可文件。使用框架来传输这些文件实际上是一种方便的分发机制,因此您经常可能希望合并一个框架,以便这些东西可以与您的二进制文件一起标记(即许可要求可能强制执行此操作)。

--- 编辑 ---

Adam Johns 发表了以下问题作为评论:

This is a great answer. There is something I'm still a little confused on, however. What does it mean to execute the binary yourself? Do you mean simply using the embedded framework's code? I know you mentioned popen(), but you're saying my app is calling popen()? I don't really know what that means.

我是说 嵌入式二进制文件 只是您的包中的另一个资源文件,如音频文件或图像,尽管该文件是可执行文件 command-line工具。 popen() 函数(man popen 从你的终端阅读更多关于它的信息)允许你从另一个 运行ning 程序执行任意程序。 system() 函数是另一种方式。还有其他的,我将在这里给出一个历史示例,它可以使对嵌入式二进制文件的使用的理解更加清楚:

您可能已经知道,当您在 Mac OS X 上启动应用程序时,它会使用当前用户的用户 ID 启动。在最常见的安装中,这是默认的 user-at-the-Desktop admin 用户,其用户 ID 为 501.

在 Unix-based 操作系统上,只有 root 用户(用户 ID 0)可以完全访问整个文件系统。有时,桌面用户启动的安装程序需要在特权目录中安装文件(例如驱动程序)。在这种情况下,应用程序需要将其权限提升到 root 用户,以便它可以写入这些受限目录。

为了通过 OS X 10.7 在操作系统中促进这一点,Apple 在其 Authorization Services API the function AuthorizationExecuteWithPrivileges() 中提供(现在已弃用,但仍然是一个有用的示例)。

AuthorizationExecuteWithPrivileges() 将 command-line 工具的路径作为参数作为 root 执行。命令行工具是一个可执行的 shell 脚本或您写入 运行 安装逻辑的编译二进制文件。就像任何其他资源文件一样,此工具已安装在您的应用程序包中。

调用时,OS 会弹出一个授权对话框,要求用户输入密码(您以前见过这个!),输入后会代表您的应用以 root 身份执行程序.此过程类似于您自己使用 popen() 执行程序,尽管仅 popen() 并不能为您带来特权升级的好处。

简而言之,

  • system libraries, link them;
  • 3rd party libraries, embed them.

为什么?

  • if you try to embed system libraries, you won't find them in the popup list;
  • if you link 3rd party libraries, you'll probably get a crash.

Xcode v11 之前的版本。嵌入式二进制文件与 Linked 框架和库

历史

Embedded Binaries vs Linked Frameworks and Libraries -> Frameworks, Libraries, and Embedded Content

[Xcode v11. Frameworks, Libraries, and Embedded Content]General 选项卡中的 Xcode v11 部分替换了它

embedded binariesLinked FrameworksDependency 管理的一部分 [About]

[Xcode v11]

Link二进制

General -> Linked Frameworks and LibrariesBuild Phases -> Link Binary With Libraries.

的镜像

静态库和框架

如果您将 Static Library or Static Framework 添加到此部分,它将出现在 Frameworks group(Project Navigator -> <workspace/project> -> Frameworks) 和将为您的项目添加一个参考。然后它将被Static Linker使用。 Static Linker在编译时将include/copy库中的所有代码放入可执行目标文件中。 Static linkerBuild Settings -> <Library/Framework> Search Paths

配对使用

Static Library

  • Build Settings -> Library Search Paths[library not found] If you do not add a static library to this section you will get a linker error[ld: symbol(s) not found]

Static Framework

  • Build Settings -> Framework Search Paths。如果你不在这个部分添加 static framework 你会得到一个编译错误

嵌入二进制文件

静态库和静态框架

嵌入对于 Static LibraryStatic Framework 没有任何意义,因为它们的符号被编译成可执行二进制文件。 Xcode 不会让你在嵌入部分下放置 static library

动态框架

General -> Embedded BinariesBuild Phases -> Embed Frameworks.

的镜像

嵌入实际上 将框架的副本 添加到您的应用程序包中(不是将框架和应用程序的代码合并到单个可执行二进制文件中)

默认情况下,包的文件夹是 Frameworks,但您可以使用 Destination 字段更改它。此外,您可以指定 Subpath.

Dynamic linker :dyld 加载或 运行 时间 将尝试使用 [=39] 找到 嵌入式框架 =][About] If it is not found the error will occur [dyld: Library not loaded]

结果:

  • Static Library - Link
  • Static Framework - Link
  • Dynamic Framework - Embed


[When use Link and Embed]
[Vocabulary]