ios 我们什么时候应该在 Xcode 中使用“嵌入式二进制文件”而不是“链接框架”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32675272/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 07:44:11  来源:igfitidea点击:

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

iosxcodeframeworksembedded-binary

提问by Forrest

There is a good question about the difference between those two options as described in Link Binary with libraries VS Embed Frameworks.

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

Seems like we have options to use them both, just wonder which case we should use embedded binaries better, or rather than linked framework ?

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

Any solid examples to address this more clear? Thanks

有什么可靠的例子可以更清楚地解决这个问题吗?谢谢

回答by par

The question you linked references the "Link Binary With Libraries" functionality, which is somewhat different than an embedded binary.

您链接的问题引用了“Link Binary With Libraries”功能,该功能与嵌入式二进制文件有些不同。

"Link Binary With Libraries" means what you'd expect it to with respect to linkage: Regardless of whether the binary is a static library, dynamic library, or framework it will be linked to your object code at link time after compilation.

“Link Binary With Libraries”意味着您对链接的期望:无论二进制文件是静态库、动态库还是框架,它都会在编译后的链接时链接到您的目标代码。

When you think of linkage with a static library, what happens is pretty clear: the linker copiesthe code from the library (e.g. libFoo.a) into your output binary. Your output file grows in size but doesn't need to resolve any external dependencies at runtime. Everything your program needs to run (with respect to the static library) is present after it is built.

当您想到与静态库的链接时,会发生什么很清楚:链接器将库中的代码(例如)复制libFoo.a到您的输出二进制文件中。您的输出文件会变大,但不需要在运行时解析任何外部依赖项。程序运行所需的一切(相对于静态库)在构建后都已存在。

With a dynamic library (.dylib, or system-supplied framework), the expectation is that the library you are linking against will be present somewhere in the system's dynamic-library loader path when you run your program. This way you don't have the overhead of copying all the third party external libraries into your binary, and all the different programs on a computer that also link to that library will be able to find it, which saves minimally disk space, but also potentially memory space, depending on how and where the system caches libraries.

使用动态库(.dylib 或系统提供的框架)时,期望您链接的库在您运行程序时出现在系统的动态库加载器路径中的某个位置。这样你就没有将所有第三方外部库复制到你的二进制文件中的开销,并且计算机上所有链接到该库的不同程序都可以找到它,这节省了最少的磁盘空间,而且潜在的内存空间,取决于系统缓存库的方式和位置。

A framework is much like a dynamic library, but can contain resources in its directory structure (images, audio, other frameworks, etc.). In this case a simple static-library or .dylib file won't cut it so you might have to link to a framework just so itcan find what it needs to run properly.

框架很像动态库,但可以在其目录结构中包含资源(图像、音频、其他框架等)。在这种情况下,一个简单的静态库或名为.dylib文件将不会削减它,所以你可能需要链接到一个框架,只是这样可以找到它所需要的正常运行。

When you link to a third-party framework (say something you downloaded from github and built yourself), it might not be present on the system you intend to run on. In this case, you'd not only link to the framework, but embed it inside your application bundle as well using the "Copy Frameworks" phase. When your program runs, the runtime-linker (aka the resolver) will look inside your bundle in addition to the system loader path, find the embedded framework, and link it so your app will have the code it needs in order to run.

当您链接到第三方框架(比如您从 github 下载并自己构建的框架)时,它可能不会出现在您打算运行的系统上。在这种情况下,您不仅要链接到框架,还要使用“复制框架”阶段将其嵌入到应用程序包中。当您的程序运行时,运行时链接器(也称为解析器)将在您的包中查看系统加载器路径之外的内容,找到嵌入式框架并链接它,以便您的应用程序拥有运行所需的代码。

Finally, what is properly an "embedded binary" is an executable you both embed in your application bundle via a Copy-Files Phase, and that you execute yourself, perhaps with a call to popen()or similar. The embedded binary may be called by your program, but it isn't linked with it. It is a fully external entity (like programs in the /bindirectory).

最后,所谓的“嵌入式二进制文件”是一个可执行文件,您可以通过复制文件阶段将其嵌入到应用程序包中,并且您自己执行,可能会调用popen()或类似的方法。嵌入的二进制文件可能会被您的程序调用,但并未与其链接。它是一个完全外部实体(如/bin目录中的程序)。

In practice, for system-supplied libraries and frameworks you will link against them and that's all you need to do.

实际上,对于系统提供的库和框架,您将针对它们进行链接,这就是您需要做的全部工作。

If you need to link a library you built that doesn't need any embedded resources (i.e. doesn't require a framework to exist), then you can just link against a static library. If you find you have multiple modules in your program that want to use the same library code, then converting it to a framework or dynamic library and linking against that can save space and may be convenient (particularly if memory usage is a concern).

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

Finally, frameworks can include not only resources, but header and/or license files. Using a framework to convey these files is actually a convenient distribution mechanism so often you may want to incorporate a framework just so these things can tag along with your binary (i.e. license requirements may make this mandatory).

最后,框架不仅可以包含资源,还可以包含头文件和/或许可证文件。使用框架来传送这些文件实际上是一种方便的分发机制,因此您可能经常希望合并一个框架,以便这些东西可以与您的二进制文件一起标记(即许可证要求可能使这成为强制性)。

--- EDIT ---

- - 编辑 - -

Adam Johns posted the following question as a comment:

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.

这是一个很好的答案。然而,有一点我仍然有点困惑。自己执行二进制文件是什么意思?你的意思是简单地使用嵌入式框架的代码?我知道你提到了 popen(),但你是说我的应用程序正在调用 popen()?我真的不知道那是什么意思。

I'm saying an embedded binaryis just another resource file in your bundle, like an audio file or image, although the file is instead an executable command-line tool. The popen()function (man popenfrom your terminal to read more about it) lets you execute arbitrary programs from another running program. The system()function is another way. There are others, and I'll give a historical example here that may make understanding use of an embedded binary a bit more clear:

我是说嵌入的二进制文件只是你的包中的另一个资源文件,比如音频文件或图像,尽管该文件是一个可执行的命令行工具。该popen()功能(man popen从您的终端阅读有关它的更多信息)允许您从另一个正在运行的程序中执行任意程序。该system()功能是另一种方式。还有其他的,我将在这里举一个历史例子,可以让你更清楚地理解嵌入式二进制文件的使用:

As you're probably aware, when you launch an app on Mac OS X it is launched with a user id of the current user. Under most common installations that's the default user-at-the-Desktop adminuser, who is given user id 501.

您可能知道,当您在 Mac OS X 上启动应用程序时,它会使用当前用户的用户 ID 启动。在最常见的安装中,这是默认的桌面admin用户用户,被赋予用户 id 501

On Unix-based operating systems only the rootuser (user id 0) has full access to the entire filesystem. Sometimes it happens that an installer program launched by the Desktop user needs to install files in a privileged directory (drivers for example). In this case, the application program needs to escalate its privileges to the rootuser so it can write in these restricted directories.

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

To facilitate this in operating systems through OS X 10.7, Apple provided in its Authorization Services APIthe function AuthorizationExecuteWithPrivileges()(this is now deprecated, but is still a useful example).

为了通过 OS X 10.7 在操作系统中实现这一点,Apple 在其授权服务 API 中提供了函数AuthorizationExecuteWithPrivileges()(现在已弃用,但仍然是一个有用的示例)。

AuthorizationExecuteWithPrivileges()took as an argument a path to a command-line tool to execute as root. The command line tool was an executable shell script or compiled binary that you wrote to run your install logic. This tool was installed inside your application bundle just like any other resource file.

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

When called, the OS put up an authorization dialog asking for the user's password (you've seen this before!) and when entered would execute the program as rooton your app's behalf. This process is similar to just executing a program with popen()yourself, although popen()alone doesn't give you the benefit of privilege escalation.

当被调用时,操作系统会显示一个授权对话框,要求输入用户的密码(你以前见过这个!),当输入时,它会root代表你的应用程序执行程序。这个过程类似于popen()自己执行一个程序,尽管popen()单独执行并不能给您带来提权的好处。

回答by Bright Future

In short,

简而言之,

  • system libraries, link them;
  • 3rd party libraries, embed them.
  • 系统库,链接它们;
  • 第 3 方库,嵌入它们。

why?

为什么?

  • 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.
  • 如果您尝试嵌入系统库,则不会在弹出列表中找到它们;
  • 如果您链接第 3 方库,您可能会崩溃。

回答by yoAlex5

It is a part of Dependencymanagement [About]

它是Dependency管理的一部分[关于]

Please note that Xcode 11contains only Frameworks, Libraries, and Embedded Contentsection in Generaltab

请注意,Xcode 11仅包含选项卡中的Frameworks, Libraries, and Embedded Content部分General

Link Binary

链接二进制

Build Phases -> Link Binary With Librariesis a mirror of General -> Linked Frameworks and Libraries.

Build Phases -> Link Binary With Libraries是 的一面镜子General -> Linked Frameworks and Libraries

Static Library and Framework

静态库和框架

If you add a Static Library or Static Frameworkto this section it will appear at Frameworksgroup[About](Project Navigator -> <workspace/project> -> Frameworks) and there will be a reference added to your project for it. Then it will be used by Static Linker. Static Linkerat compile time will include/copyall code from the library into the executable object file. Static linkerworks in pair with Build Settings -> <Library/Framework> Search Paths

如果添加Static Library or Static Framework到本节将出现在Frameworks[关于]Project Navigator -> <workspace/project> -> Frameworks),而且将被添加到您的项目为它的参考。然后它将被Static Linker. Static Linker在编译时会将库中的所有代码包含/复制到可执行对象文件中。Static linker配对工作Build Settings -> <Library/Framework> Search Paths

Static Library

Static Library

Static Framework

Static Framework

  • Build Settings -> Framework Search Paths. If you do not add a static frameworkto this section you will get a compile error[No such module]
  • Build Settings -> Framework Search Paths. 如果你不添加 astatic framework到这个部分,你会得到一个编译错误[No such module]

Embed binary

嵌入二进制

Static Library and Static Framework

静态库和静态框架

Embedding wouldn't make any sense for a Static Libraryand Static Frameworkbecause the symbols from them are compiled into the executable binary. Xcode won't let you drop a static libraryunder the Embed section.

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

Dynamic Framework

动态框架

Build Phases -> Embed Frameworksis a mirror of General -> Embedded Binaries. Embedding actually adds a copyof the framework into your application bundle. As a result, when a framework is added/removed to Embedsection it will be automatically added/removed to Linkedsection. By default the bundle's folder is Frameworksbut you can change it using Destinationfield. Moreover you can specify a Subpath.

Build Phases -> Embed Frameworks是 的一面镜子General -> Embedded Binaries。嵌入实际上是框架的副本添加到您的应用程序包中。因此,当一个框架被添加/删除到Embed部分时,它会自动添加/删除到Linked部分。默认情况下,bundle 的文件夹是,Frameworks但您可以使用Destinationfield更改它。此外,您可以指定一个Subpath.

Dynamic linker :dyldat load or run timewill try to find the embedded frameworkusing @rpath[About]If it is not found the error will occur [dyld: Library not loaded]

Dynamic linker :dyld加载或运行时将尝试使用[About]查找嵌入式框架,如果未找到,则会发生错误[dyld: Library not loaded]@rpath

[When use Link and Embed]

[使用链接和嵌入时]

[Vocabulary]

[词汇]