有一个关于这两个选项之间的差异的好问题,如链接二进制库VS嵌入框架中所述。
似乎我们可以同时使用它们,只是想知道在哪种情况下我们应该更好地使用嵌入式二进制文件,还是使用链接框架?
有没有更清晰的实例来说明这一点?谢谢
v11之前的Xcode。嵌入式二进制文件与链接框架和库
历史
Embedded Binaries vs Linked Frameworks and Libraries -> Frameworks, Libraries, and Embedded Content
[Xcode v11.框架、库和嵌入式内容]取代了常规
选项卡中的Xcode v11部分
嵌入式二进制文件
和链接框架
是依赖关系
管理的一部分[About]
[Xcode v11]
概述-
静态库和框架
如果将
静态库或静态框架
添加到此部分,它将出现在框架
组[About](项目导航器-
静态库
构建设置-
静态框架
构建设置-
静态库与静态框架
嵌入对于
静态库
和静态框架
没有任何意义,因为它们的符号被编译成可执行二进制文件。Xcode不允许您将静态库
放在嵌入部分下。
动态框架
概述-
嵌入实际上是将框架的副本添加到应用程序包中(而不是将框架和应用程序的代码合并到单个可执行二进制文件中)
默认情况下,捆绑包的文件夹是
Frameworks
,但您可以使用Destination
字段更改它。此外,还可以指定子路径
。
动态链接器: dyld
在加载或运行时将尝试使用@rpath
[About]找到嵌入式框架如果没有找到,将发生错误[dyld:库未加载]
结果:
静态库
-链接
静态框架
-链接
动态框架
-嵌入
[静态与动态链接器]
[使用链接和嵌入时]
[词汇]
简言之
为什么?
您链接的问题引用了“将二进制文件链接到库”功能,这与嵌入式二进制文件有些不同。
“将二进制文件与库链接”指的是与链接相关的内容:无论二进制文件是静态库、动态库还是框架,它都将在编译后的链接时间链接到您的目标代码。
当您想到与静态库的链接时,发生的事情非常清楚:链接器将库中的代码(例如libFu. a
)复制到您的输出二进制文件中。输出文件的大小会增加,但不需要在运行时解决任何外部依赖项。程序运行所需的一切(相对于静态库)在构建后都存在。
对于动态库(.dylib,或系统提供的框架),当您运行程序时,您所链接的库将出现在系统的动态库加载程序路径中的某个位置。通过这种方式,您不需要将所有第三方外部库复制到二进制文件中,并且计算机上所有链接到该库的不同程序都可以找到它,这将节省最少的磁盘空间,但也可能节省内存空间,具体取决于系统缓存库的方式和位置。
框架很像动态库,但可以在其目录结构中包含资源(图像、音频、其他框架等)。在本例中,是一个简单的静态库或。dylib文件不会剪切它,所以您可能需要链接到一个框架,这样它才能找到正确运行所需的内容。
当你链接到第三方框架(比如你从github下载并自己构建的东西)时,它可能不会出现在你想要运行的系统上。在这种情况下,您不仅要链接到框架,还要使用“复制框架”阶段将其嵌入到应用程序包中。当你的程序运行时,运行时链接器(又名解析器)除了查看系统加载程序路径外,还会查看你的包,找到嵌入的框架,并将其链接,这样你的应用程序就可以获得运行所需的代码。
最后,真正的“嵌入式二进制文件”是一个可执行文件,您可以通过复制文件阶段将其嵌入到应用程序包中,然后自己执行,可能需要调用popen()
或类似的程序。嵌入的二进制文件可能会被你的程序调用,但它没有与之链接。它是一个完全外部的实体(如/bin
目录中的程序)。
实际上,对于系统提供的库和框架,您将链接到它们,这就是您需要做的一切。
如果需要链接一个不需要任何嵌入式资源(即不需要框架存在)的库,那么只需链接一个静态库即可。如果您发现程序中有多个模块想要使用相同的库代码,那么将其转换为框架或动态库,并根据这些模块进行链接可以节省空间,而且可能很方便(尤其是在内存使用是一个问题的情况下)。
最后,框架不仅可以包括资源,还可以包括头文件和/或许可证文件。使用一个框架来传输这些文件实际上是一种方便的分发机制,因此您可能经常希望合并一个框架,以便这些东西可以与二进制文件一起标记(即,许可证要求可能会强制要求这样做)。
---编辑---
亚当·约翰斯(Adam Johns)发表了以下问题作为评论:
这是一个伟大的答案。然而,有些事情我仍然有点困惑。自己执行二进制是什么意思?你的意思是简单地使用嵌入式框架的代码吗?我知道你提到了popen(),但你是说我的应用程序正在调用popen()?我真的不知道那是什么意思。
我是说嵌入式二进制文件只是捆绑包中的另一个资源文件,比如音频文件或图像,尽管该文件是可执行的命令行工具。popen()
函数(man popen
从您的终端阅读更多关于它的信息)允许您从另一个正在运行的程序中执行任意程序。system()
函数是另一种方式。还有其他的例子,我将在这里给出一个历史例子,它可以让对嵌入式二进制的理解更加清晰:
正如您可能知道的,当您在Mac OS X上启动应用程序时,它是使用当前用户的用户id启动的。在大多数常见安装中,这是桌面上的默认用户admin
user,用户id为501
。
在基于Unix的操作系统上,只有root
用户(user id0
)才能完全访问整个文件系统。有时,桌面用户启动的安装程序需要安装特权目录中的文件(例如驱动程序)。在这种情况下,应用程序需要将其权限升级到root
用户,以便可以在这些受限目录中写入。
为了通过OS X 10.7在操作系统中促进这一点,苹果在其授权服务应用编程接口中提供了函数AuthorizationExekteAnd Privileges()(现在不建议使用,但仍然是一个有用的示例)。
AuthorizationExecuteWithPrivileges()
将命令行工具的路径作为参数,以根目录执行。命令行工具是一个可执行的shell脚本或编译的二进制文件,您编写它来运行安装逻辑。与其他资源文件一样,该工具安装在应用程序包中。
当被调用时,操作系统会显示一个授权对话框,询问用户的密码(你以前见过这个!)当输入时,将代表应用程序以
root
的形式执行程序。这个过程类似于你自己用popen()
执行一个程序,尽管popen()
本身并不能给你提权。
关于这两个选项之间的区别,有一个很好的问题,如链接二进制与库VS嵌入式框架中所述。 似乎我们有两种选择都可以使用,只是想知道哪种情况下我们应该更好地使用嵌入式二进制文件,还是而不是链接框架?
问题内容: 我是一名C ++程序员,偶尔使用MySQL处理数据库,但是我的SQL知识非常有限。但是,我当然愿意改变这一点。 目前,我正尝试仅通过SQL查询对数据库中的数据进行分析(!)。但是我将放弃,而是将数据导入C 并使用C 代码进行分析。 我已经与同事讨论了这一点,他们也促使我使用C ++,他说SQL并不是用于复杂的分析,而是主要用于导入(从现有表中)和导出(到新表中)数据,还有更多内容。例如
问题内容: 我正在使用’multiprocess.Pool.imap_unordered’如下 我需要打电话或之后的for循环? 问题答案: 不,您没有,但是如果您不再使用游泳池,那可能是个好主意。 Tim Peters在此SO帖子中致电或致电的理由很明确: 至于Pool.close(),您应该在永远不会将更多工作提交给Pool实例的情况下(且仅在)进行调用。因此,通常在主程序的可并行化部分完成时
问题内容: 面试官问我: 什么是Observer,什么Observable时候应该使用它们? 我并不了解这些术语,因此当我回到家并开始使用GoogleObserver和Google搜索时Observable,从不同的资源中发现了一些要点: 1)Observable是一个类,Observer是一个接口。 2)Observable该类维护一个Observers的列表。 3)当一个Observable对
我有两个文件,第一个是todoHelper。js 它有 导入{addTodo} 但我也看到人们在做默认导出,而不仅仅是导出。有什么区别?
问题内容: 我在ORM上还很新。我刚刚开始阅读有关使用Hibernate的Java Persistence API的书籍和文档。 我只是想知道,关闭EntityManagerFactory与jdbc数据库连接关闭类似吗? 我们是否应该在每次持久/更新/删除后关闭它?如果我们不关闭它,数据库连接会保持打开状态吗? 问题答案: 我只是想知道,关闭与jdbc数据库连接关闭类似吗? 这并非完全正确,但关闭