我创建了一个包含所有泛型类的静态库。其中一些类使用框架。
现在我有两个项目,一个使用一些使用框架的类,另一个不使用任何使用框架的类。
因为静态库不支持包含框架(如果我是正确的)。我必须在使用它们的项目中包含框架。但是,当我编译不使用任何框架类的项目时,编译器会中断,因为它仍然需要框架。现在我知道它试图从库中编译所有(未使用的)类,因为我使用链接器标记'-ObjC'来防止'无法识别的选择器'错误。
有谁知道如何只为每个项目编译所需的源文件?并且阻止所有框架必须包含在使用我的静态库的所有项目中?
答案 0 :(得分:15)
首先,你是对的,静态库不能包含任何框架或其他静态库,它只是构成该特定静态库的所有目标文件(* .obj)的集合。
有谁知道如何只为每个项目编译所需的源文件?
默认情况下,链接器仅链接来自包含应用程序引用的符号的静态库的目标文件。因此,如果静态库中有两个文件a.m
和b.m
,并且只在主程序中使用a.m
中的符号,那么b.o
(从中生成的目标文件) b.c
)不会出现在您的最终可执行文件中。作为子案例,如果b.m
使用仅声明(未实现)的函数/类c
,那么您将不会收到任何链接器错误。只要在程序中包含b.m
中的某些符号,b.o
也会被链接,并且由于缺少c
的实现,您将收到链接器错误。
如果您希望此类选择以符号而非对象级粒度发生,请在Xcode中启用死代码剥离。这对应于项目的“构建设置信息”窗格中的gcc选项-Wl,-dead_strip(=链接器选项-dead_strip)。这将确保进一步优化。
在你的情况下,正如你正确地说的那样,使用“-ObjC”链接器标志会破坏这种机制。所以这实际上取决于你。如果删除-Objc标志,则可以免费获得您喜欢的行为,同时对选择器进行更严格的检查。
并且阻止所有框架必须包含在使用我的静态库的所有项目中?
Xcode / GCC支持一个称为“weak linking”的链接选项,它允许延迟加载框架或静态库,即,仅当实际使用其中一个符号时。 “弱链接”可以通过链接器标志(参见上面的Apple文档)或通过Xcode UI(目标 - >信息 - >常规 - >链接库)启用。
无论如何,在编译/链接时,框架或库必须在所有情况下都可用:“weak”选项仅影响框架在运行时首次加载的时刻。因此,我不认为这对您有用,因为您无论如何都需要在所有项目中包含框架,这是您不想要的。
作为旁注,weak_linking
是一个选项,当使用仅在较新的SDK版本(例如,4.3.2)上提供的功能时,通常是有意义的,同时还支持在较旧的SDK版本上部署(例如,3.1.3) )。在这种情况下,您依赖于以下事实:较新的SDK框架将在较新的部署设备上实际可用,并且您有条件地编译需要它的功能,以便在旧设备上不需要它们(并且不会因此而产生)尝试加载更新版本的框架和崩溃)。
更糟糕的是,GCC不支持与Microsoft编译器称为“自动链接”的功能,它允许通过源文件中的#pragma注释指定要链接的库。这可以提供一种解决方法,但不存在。
所以,我很遗憾不得不说你应该采用一种同样满足你需求的不同方法:
删除-ObjC标志;
根据外部框架的依赖关系将静态库拆分为两个或多个部分;
直接包含源文件。
答案 1 :(得分:5)
在问题的第二部分,您可以将链接框架标记为Optional
:
关于第一部分,我不清楚你打算做什么:
#ifdef
...),但这取决于你想做什么。答案 2 :(得分:0)
听起来你有图书馆臃肿。为了保持简洁,我认为您需要将库重构为具有最小依赖性的单独库。您可以尝试在构建目标信息(Xcode 3.x)的“链接器标志”部分中打开“死代码剥离”,看看它是否符合您的要求(不需要被剥离的类使用的框架) 。)
当您链接到iOS上的框架时,我认为这不会真正增加任何膨胀,因为框架在设备上,而不在您的应用程序中。但是你的库仍然有点臃肿,因为整个类从来没有被使用但是没有从库中删除。
答案 3 :(得分:0)
在编译应用程序之前构建静态库,然后将整个内容链接到您的应用程序中。没有办法包括图书馆的某些部分而不包括其他部分 - 你得到整个辣酱玉米饼馅。
由于您拥有库的源代码,为什么不直接将代码添加到每个应用程序?这样您就可以准确控制每个应用程序的内容。您仍然可以将通用类保存在同一位置,并在两个应用程序中使用相同的代码,但您可以避免使用库的麻烦。