关于Link Binary with libraries VS Embed Frameworks中描述的这两个选项之间的区别,有一个很好的问题。
似乎我们可以选择同时使用它们,只是想知道哪种情况我们应该更好地使用嵌入式二进制文件,或者不是链接框架?
任何可以解决这个问题的可靠实例更清楚?感谢
答案 0 :(得分:205)
您链接的问题引用了" Link Binary With Libraries"功能,与嵌入式二进制文件略有不同。
"将二进制文件链接到库"表示您对链接的期望:无论二进制文件是静态库,动态库还是框架,它都会在编译后的链接时链接到您的目标代码。
当您考虑与静态库的链接时,发生的事情非常清楚:链接器将库中的代码(例如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在其Authorization Services API中提供了函数AuthorizationExecuteWithPrivileges()(现在已弃用,但仍然是一个有用的示例)。
AuthorizationExecuteWithPrivileges()
将命令行工具的路径作为参数作为root
执行。命令行工具是您编写的用于运行安装逻辑的可执行shell脚本或编译二进制文件。此工具已安装在应用程序包中,就像任何其他资源文件一样。
当被叫时,操作系统会设置一个授权对话框,询问用户的密码(您之前已经看到过这个密码!),输入后会在您的应用上以root
执行该程序&# 39;代表。此过程类似于仅使用popen()
执行某个程序,但仅popen()
并不能为您提供权限提升的好处。
答案 1 :(得分:21)
简而言之,
- 系统库,链接它们;
- 第三方图书馆,嵌入它们。
为什么?
- 如果您尝试嵌入系统库,则无法在弹出列表中找到它们;
- 如果您链接第三方库,您可能会崩溃。
答案 2 :(得分:0)
它是Dependency
管理[About]
请注意,Xcode 11
在Frameworks, Libraries, and Embedded Content
标签中仅包含General
部分
Build Phases -> Link Binary With Libraries
是General -> Linked Frameworks and Libraries
的镜像。
静态库和框架
如果在此部分添加Static Library or Static Framework
,它将显示在Frameworks
组中,并且为此项目将添加一个引用。然后Static Linker
将使用它。 Static Linker
在编译时会将所有代码从库中包括/复制到可执行目标文件中。
Static Library
static library
,则会出现链接器错误[ld: symbol(s) not found]。此外,Static linker
与Build Settings -> Library Search Paths
[library not found]配对使用 Framework
它应该与Build Settings -> Framework Search Paths
[No such module]
static framework
,则会出现编译错误[No such module]。dynamic framework
的本节。静态库和静态框架
对于Static Library
和Static Framework
而言,嵌入没有任何意义,因为它们中的符号已被编译到可执行文件中。 Xcode不允许您在“嵌入”部分下放置static library
。
动态框架
Build Phases -> Embed Frameworks
是General -> Embedded Binaries
的镜像。实际上,嵌入会将框架的副本添加到您的应用程序包中。结果,在将框架添加/删除到Embed
部分时,它将自动添加/删除到Linked
部分。默认情况下,捆绑软件的文件夹为Frameworks
,但您可以使用Destination
字段进行更改。此外,您可以指定Subpath
。
Dynamic linker :dyld
在加载或运行时会尝试使用@rpath
[About]找到嵌入式框架(如果找不到)错误将发生[dyld: Library not loaded]