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

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

问题描述

关于中描述的这两个选项之间的区别,这是一个很好的问题。链接Binary与库VS嵌入框架



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



任何可以解决这个问题的可靠实例更清楚?谢谢

解决方案

您链接的问题引用了Link Binary With Libraries功能,这与嵌入式二进制文件略有不同。 / p>

链接二进制文件库意味着你对链接的期望是什么:无论二进制文件是静态库,动态库还是框架,它都会在编译后的链接时链接到目标代码。



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



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



框架很像动态库,但可以在其目录结构中包含资源(图像,音频) ,其他框架等)。在这种情况下,一个简单的静态库或.dylib文件不会删除它,因此您可能必须链接到框架,因此可以找到正常运行所需的内容。



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

最后,什么是嵌入式二进制文件是一个可执行文件,你可以通过复制文件阶段嵌入应用程序包中,并且你自己执行,也许是致电 popen()或类似。嵌入式二进制文件可能由您的程序调用,但它不与它链接。它是一个完全外部的实体(如 / bin 目录中的程序)。



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



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

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



---编辑---



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


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


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



正如你可能知道的那样,在Mac OS X上启动应用程序时,它会以当前用户的用户ID启动。在大多数常见安装下,这是默认的桌面用户 admin 用户,其用户ID 501



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



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



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



当被调用时,操作系统会建立一个授权对话框,询问用户的密码(你看过了)这之前!)并且在输入时将代表您的应用程序以 root 执行程序。这个过程类似于自己用 popen()执行一个程序,虽然 popen()单独不给你获得了特权升级的好处。


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

解决方案

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

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

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.

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.

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.

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.

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

--- EDIT ---

Adam Johns posted the following question as a comment:

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.

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:

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.

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.

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

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天全站免登陆