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

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

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

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

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

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

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

链接器默认只链接来自静态库的包含应用程序引用的符号的目标文件。 因此,如果在静态库中有两个文件ambm ,并且只使用主程序中的符号,那么bo (从bc生成的目标文件)不会出现在最终的可执行文件中。 作为一个子情况,如果bm使用一个只声明(未实现)的函数/类c ,那么你将不会得到任何链接错误。 只要在程序中包含一些bm符号, bo也会被链接,并且由于缺lessc实现,将会出现链接器错误。

如果你希望这种select发生在符号而不是在对象级粒度,在Xcode中启用死代码剥离。 这对应于gcc选项-Wl,-dead_strip(=您的项目的“生成设置信息”窗格中的链接器选项-dead_strip)。 这将确保进一步的优化。

就你而言,正如你所说的那样,正是使用了“-ObjC”链接器标志来击败这个机制。 所以这实际上取决于你。 如果你删除了-Objc标志,你会得到你喜欢的行为,同时失去对select器的更严格的检查。

并防止所有框架必须包含在所有使用我的静态库的项目中?

Xcode / GCC支持一个被称为“ 弱链接 ”的链接选项,它允许延迟地加载一个框架或静态库,即只有当其中一个符号被实际使用时。 可以通过链接标志(参见上面的Apple文档)或通过Xcode UI(目标 – >信息 – >常规 – >链接库)启用“弱链接”。

无论如何,在编译/链接时,框架或库必须在所有情况下都可用:“弱”选项只影响在运行时第一次加载框架的时刻。 因此,我不认为这对你有用,因为无论如何你都需要把框架包含在你所有的项目中,这是你不想要的。

作为一个侧面说明, weak_linking是一个非常有意义的select,当使用仅在更新的SDK版本(如4.3.2)上可用的function时,同时也支持在较旧的SDK版本(如3.1.3)上部署。 在这种情况下,您依赖于较新的SDK框架将在新的部署设备上实际可用的事实,并且有条件地编译需要它的function,以便在较旧的设备上它们将不被需要(并且将不会尝试加载更新版本的框架和崩溃)。


更糟糕的是,GCC不支持Microsoft编译器的一种称为“自动链接”的function,它允许通过源文件中的#pragma注释来指定要链接哪个库。 这可能会提供解决方法,但不在那里。


所以,我非常抱歉不得不说,你应该使用不同的方法,可以同样满足您的需求:

  1. 删除-ObjC标志;

  2. 根据外部框架的依赖关系将静态库分成两个或两个以上的部分;

  3. 诉诸直接包含源文件。

放弃问题的第二部分,您可以将链接的框架标记为Optional可选框架

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

  • 在一个项目中声明一个库
  • 声明哪些文件被编译的项目(通过目标>生成阶段>编译源文件)
  • 除非设置复杂的构build规则来包含或不包含文件,如果我记得很好,可以使用.xcconfig文件来完成,我没有看到任何其他解决scheme,而不是分割您的库。 我会build议,因为它的方便。 你甚至应该在同一个项目中做好几个目标…你也可以使用预编译器的MACROS( #ifdef …),但这取决于你想要做什么。

这听起来像你有图书馆膨胀。 为了保持小事我认为你需要重构你的库到最小的依赖关系的单独的库。 您可以尝试在构build目标信息(Xcode 3.x)的“链接器标志”部分中打开“死代码剥离”,以查看是否按照您的要求进行了操作(不需要被死去的类使用的框架。)

当你链接到iOS上的框架,我不认为这真的增加了任何膨胀,因为框架是在设备上,而不是在你的应用程序。 但是,你的图书馆仍然有点臃肿,整个类从来没有被使用过,但没有被剥离出图书馆。

在编译应用程序之前build立一个静态库,然后将整个事物链接到您的应用程序中。 没有办法包括图书馆的某些部分,但不包括其他人 – 你得到整个辣酱玉米饼馅。

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