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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6009175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 21:01:53  来源:igfitidea点击:

Static Library using frameworks in specific projects

objective-cxcodeios

提问by Thizzer

I have created a static library containing all my generic classes. Some of these classes use frameworks.

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

Now I have two projects, one that uses some classes that use frameworks, and one that doesn't use any of the classes that use frameworks.

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

Because Static Libraries don't support including frameworks (if I am correct). I have to include the frameworks in the project that uses them. But when I compile the project that doesn't use any of the framework-classes the compiler breaks because it still requires the frameworks. Now I know it tries to compile all the (unused) classes from the library because I use the Linker Flag '-ObjC' to prevent 'unrecognized selector' errors.

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

Does anyone know how to compile only the required source files per project? And prevent from all frameworks having to be included in all projects that use my static library?

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

采纳答案by sergio

First of all, you are right in that a static library cannot include any framework nor other static libraries, it is just the collection of all object files (*.obj) that make up that specific static library.

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

Does anyone know how to compile only the required source files per project?

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

The linker will by default only link in object files from the static library that contain symbols referenced by the application. So, if you have two files a.mand b.min your static library and you only use symbols from a.min your main program, then b.o(the object file generated from b.c) will not appear in your final executable. As a sub-case, if b.muses a function/class cwhich is only declared (not implemented), then you will not get any linker errors. As soon as you include some symbols from b.min your program, b.owill also be linked and you will get linker errors due to the missing implementation of c.

默认情况下,链接器将只链接静态库中包含应用程序引用的符号的目标文件。因此,如果您有两个文件a.m并且b.m在您的静态库中并且您只a.m在主程序中使用符号,那么b.o(从 生成的目标文件b.c)将不会出现在您的最终可执行文件中。作为一个子案例,如果b.m使用c仅声明(未实现)的函数/类,那么您将不会收到任何链接器错误。一旦您b.m在程序中包含一些符号,b.o也将被链接,并且由于缺少c.

If you want this kind of selection to happen at symbol rather than at object level granularity, enable dead code stripping in Xcode. This corresponds to the gcc option -Wl,-dead_strip (= linker option -dead_strip in the Build settings Info pane for your project). This would ensure further optimization.

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

In your case, though, as you correctly say, it is the use of the "-ObjC" linker flag that defeats this mechanism. So this actually depends on you. If you remove the -Objc flag, you get the behavior you like for free, while losing the stricter check on selectors.

但是,在您的情况下,正如您所说的那样,正是使用“-ObjC”链接器标志来破坏此机制。所以这实际上取决于你。如果您删除 -Objc 标志,您可以免费获得您喜欢的行为,同时失去对选择器的更严格检查。

And prevent from all frameworks having to be included in all projects that use my static library?

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

Xcode/GCC support an linking option which is called "weak linking", which allows to lazily load a framework or static library, i.e., only when one of its symbols is actually used. "weak linking" can be enabled either through a linker flag (see Apple doc above), or through Xcode UI (Target -> Info -> General -> Linked Libraries).

Xcode/GCC 支持一种称为“弱链接”的链接选项,它允许延迟加载框架或静态库,即,仅在实际使用其符号之一时。“弱链接”可以通过链接器标志(请参阅上面的 Apple 文档)或通过 Xcode UI(目标 -> 信息 -> 常规 -> 链接库)启用。

Anyhow, the framework or library must be available in all cases at compile/link time: the "weak" option only affects the moment when the framework is first loaded at runtime. Thus, I don't think this is useful for you, since you would need anyway to include the framework in all of your projects, which is what you do not want.

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

As a side note, weak_linkingis an option that mostly make sense when using features only available on newer SDK version (say, 4.3.2) while also supporting deployment on older SDK versions (say, 3.1.3). In this case, you rely on the fact that the newer SDK frameworks will be actually available on the newer deployment devices, and you conditionally compile in the features requiring it, so that on older devices they will not be required (and will not produce thus the attempt at loading the newer version of the framework and the crash).

附带说明一下,weak_linking当使用仅在较新的 SDK 版本(例如 4.3.2)上可用的功能同时还支持在较旧的 SDK 版本(例如 3.1.3)上进行部署时,这是一个最有意义的选项。在这种情况下,您依赖于较新的 SDK 框架将在较新的部署设备上实际可用的事实,并且您有条件地编译需要它的功能,以便在较旧的设备上不需要它们(并且不会产生因此尝试加载较新版本的框架和崩溃)。



To make things worse, GCC does not support a feature known as "auto-linking" with Microsoft compilers, which allow to specify which library to link by means of a #pragma comment in your source file. This could offer a workaround, but is not there.

更糟糕的是,GCC 不支持 Microsoft 编译器的“自动链接”功能,该功能允许通过源文件中的 #pragma 注释指定要链接的库。这可以提供一种解决方法,但不存在。



So, I am really sorry to have to say that you should use a different approach that could equally satisfy your needs:

因此,我真的很抱歉不得不说您应该使用不同的方法来同样满足您的需求:

  1. remove the -ObjC flag;

  2. split your static library in two or more parts according to their dependencies from external frameworks;

  3. resort to including the source files directly.

  1. 删除 -ObjC 标志;

  2. 根据它们对外部框架的依赖,将你的静态库分成两部分或更多部分;

  3. 求助于直接包含源文件。

回答by Vincent Guerci

Abour second part of your question, you can mark a linked framework as Optional: Optional framework

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

About first part, it is not clear to me what you intend to do:

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

  • A library being declared in a project
  • A project declaring which files are compiled (via Target > Build phases > Compile sources)
  • Unless setting complex build rules to include or not files, which if I remember well can be done using .xcconfig files, I don't see any other solutions than splitting your Library. Which I would recommend, for its ease. You should even do several targets in the same project... You could also just use precompiler MACROS (#ifdef...) but that depends on what you want to do.
  • 在项目中声明的库
  • 声明哪些文件被编译的项目(通过目标 > 构建阶段 > 编译源)
  • 除非设置复杂的构建规则来包含或不包含文件,如果我记得很清楚可以使用 .xcconfig 文件来完成,我看不到除了拆分库之外的任何其他解决方案。我会推荐它,因为它很容易。你甚至应该在同一个项目中做几个目标......你也可以只使用预编译器 MACROS ( #ifdef...) 但这取决于你想要做什么。

回答by Caleb

A static library is built before your app is compiled, and then the whole thing is linked into your app. There's no way to include some parts of the library but not others -- you get the whole enchilada.

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

Since you have the source code for the library, why not just add the code directly to each application? That way you can control exactly what goes into each app. You can still keep your generic classes together in the same location, and use the same code in both apps, but you avoid the hassle of using a library.

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

回答by Mark

It sounds like you have library bloat. To keep things small I think you need to refactor your library into separate libraries with minimal dependencies. You could try turning on "Dead Code Stripping" in the "Linker Flags" section of the build target info (Xcode 3.x) to see if that does what you want (doesn't require frameworks used by classes that are dead-stripped.)

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

When you link against a framework on iOS I don't think that really adds any bloat since the framework is on the device and not in your application. But your library is still a bit bloated by having entire classes that never get used but are not stripped out of the library.

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