静态库在特定项目中使用框架

时间:2011-05-15 14:59:40

标签: objective-c xcode ios

我创建了一个包含所有泛型类的静态库。其中一些类使用框架。

现在我有两个项目,一个使用一些使用框架的类,另一个不使用任何使用框架的类。

因为静态库不支持包含框架(如果我是正确的)。我必须在使用它们的项目中包含框架。但是,当我编译不使用任何框架类的项目时,编译器会中断,因为它仍然需要框架。现在我知道它试图从库中编译所有(未使用的)类,因为我使用链接器标记'-ObjC'来防止'无法识别的选择器'错误。

有谁知道如何只为每个项目编译所需的源文件?并且阻止所有框架必须包含在使用我的静态库的所有项目中?

4 个答案:

答案 0 :(得分:15)

首先,你是对的,静态库不能包含任何框架或其他静态库,它只是构成该特定静态库的所有目标文件(* .obj)的集合。

  

有谁知道如何只为每个项目编译所需的源文件?

默认情况下,链接器仅链接来自包含应用程序引用的符号的静态库的目标文件。因此,如果静态库中有两个文件a.mb.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注释指定要链接的库。这可以提供一种解决方法,但不存在。


所以,我很遗憾不得不说你应该采用一种同样满足你需求的不同方法:

  1. 删除-ObjC标志;

  2. 根据外部框架的依赖关系将静态库拆分为两个或多个部分;

  3. 直接包含源文件。

答案 1 :(得分:5)

在问题的第二部分,您可以将链接框架标记为OptionalOptional framework

关于第一部分,我不清楚你打算做什么:

  • 在项目中声明的库
  • 一个项目,声明编译了哪些文件(通过目标>构建阶段>编译源代码)
  • 除非设置复杂的构建规则以包含或不包含文件,如果我记得很清楚可以使用.xcconfig文件完成,除了拆分库之外我没有看到任何其他解决方案。我会推荐,因为它很容易。你甚至应该在同一个项目中做几个目标...你也可以使用预编译器MACROS(#ifdef ...),但这取决于你想做什么。

答案 2 :(得分:0)

听起来你有图书馆臃肿。为了保持简洁,我认为您需要将库重构为具有最小依赖性的单独库。您可以尝试在构建目标信息(Xcode 3.x)的“链接器标志”部分中打开“死代码剥离”,看看它是否符合您的要求(不需要被剥离的类使用的框架) 。)

当您链接到iOS上的框架时,我认为这不会真正增加任何膨胀,因为框架在设备上,而不在您的应用程序中。但是你的库仍然有点臃肿,因为整个类从来没有被使用但是没有从库中删除。

答案 3 :(得分:0)

在编译应用程序之前构建静态库,然后将整个内容链接到您的应用程序中。没有办法包括图书馆的某些部分而不包括其他部分 - 你得到整个辣酱玉米饼馅。

由于您拥有库的源代码,为什么不直接将代码添加到每个应用程序?这样您就可以准确控制每个应用程序的内容。您仍然可以将通用类保存在同一位置,并在两个应用程序中使用相同的代码,但您可以避免使用库的麻烦。