我们什么时候应该使用“嵌入式二进制文件"?而不是“链接框架"在 Xcode 中? [英] When should we use "embedded binaries" rather than "Linked Frameworks" in Xcode?

查看:20
本文介绍了我们什么时候应该使用“嵌入式二进制文件"?而不是“链接框架"在 Xcode 中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于这两个选项之间的区别有一个很好的问题,如中所述将二进制文件与库 VS 嵌入框架链接.

There is a good question about the difference between those two options as described in 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

推荐答案

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

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.

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

When you think of linkage with a static library, what happens is pretty clear: the linker copies the 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.

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

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 it can find what it needs to run properly.

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

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.

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

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 /bin directory).

在实践中,对于系统提供的库和框架,您将链接它们,这就是您需要做的全部.

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).

--- 编辑---

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

Adam Johns posted the following question as a comment:

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

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() 函数(来自终端的 man popen 以阅读更多相关信息)让您可以从另一个正在运行的程序中执行任意程序.system() 函数是另一种方式.还有其他的,我将在这里举一个历史例子,它可以让你更清楚地理解嵌入式二进制文件的使用:

I'm saying an embedded binary is 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 popen from 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:

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

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 admin user, who is given user id 501.

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

On Unix-based operating systems only the root user (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 root user so it can write in these restricted directories.

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

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

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

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.

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

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 root on 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.

这篇关于我们什么时候应该使用“嵌入式二进制文件"?而不是“链接框架"在 Xcode 中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆