我想创建一个静态库(实际上是一个框架,但我知道如何做这个部分),它从另一个静态库中捆绑代码。但是,原始库中的OBJC_CLASS
导出最终为未定义的符号。
例如,在Xcode 5.1.1中(除非另有说明,否则在每个步骤使用默认设置/选项):
libLibA.a
从LibA产品拖到LibB项目树中的Frameworks文件夹。LibA
从静态库旁边的include
目录拖到LibB项目树的顶层。LibB.h
,如下所示。libLibB.a
从LibB产品拖到AppC项目树中的Frameworks文件夹。LibB
从include
目录拖到顶层。LibA
从第一个项目的include
目录拖到顶层。LibA
。-[MasterViewController awakeFromNib]
),添加(void)[[LibB alloc] init]
。.m
文件的顶部,添加#import "LibB.h"
。这是上面承诺的LibB.h
:
#import <Foundation/Foundation.h>
#import "LibA.h"
@interface LibB: LibA
@end
我收到以下错误:
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_LibA", referenced from:
_OBJC_CLASS_$_LibB in libLibB.a(LibB.o)
"_OBJC_METACLASS_$_LibA", referenced from:
_OBJC_METACLASS_$_LibB in libLibB.a(LibB.o)
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
查看文件,问题很明显:
$ nm -g libLibB.a
U _OBJC_CLASS_$_LibA
0000031c S _OBJC_CLASS_$_LibB
U _OBJC_METACLASS_$_LibA
00000308 S _OBJC_METACLASS_$_LibB
U _OBJC_METACLASS_$_NSObject
U __objc_empty_cache
_OBJC_CLASS_$_LibA
和_OBJC_METACLASS_$_LibA
的符号将导出为未定义。
我可以从LibA引用方法,C函数和结构,全局变量等。甚至是Foundation对象上的类别(只要我做类别 - 虚拟技巧)。它只是类和元类对象,我无法弄清楚如何导出。
以下是我试图解决的问题:
-ObjC
作为额外的链接器标志(在所有项目中)。 (这对静态库没有任何意义,它所做的就是给你一个警告错误,告诉你这个,但每个人都向我推荐。)LibB
)。 (这也只对动态库有意义。)${PROJECT_DIR}/libLibA.a
作为“其他链接标记”(针对LibB
)传递,而不是将libLibA
添加为框架(如果-lLibA
的处理方式与{{1}不同}})。我曾尝试过的,我仍然认为可能是在正确的道路上,但我不确定:
libLibA.a
选项。 (如果需要,我可以将它包装在Makefile中,或者Xcode自定义构建步骤。)libtool
添加到“预链接库”。我得到关于重复符号的警告然后成功,但是空${PROJECT_DIR}/libLibA.a
,所以显然我还需要做其他事情。我已经在OS X上用.dylibs和动态框架完成了这个,而且我没有其他任何东西需要在那里做......但是从来没有使用静态库。我了解的解决方法(如果没有真正的解决方案,我会使用其中一种方法):
libLibB.a
的人也必须将LibB
添加到他们的项目中。特别是我们提供的预先构建的LibA
副本。LibA
分发为要包含在项目中的源代码,而不是静态的lib和头文件。LibB
ar
和libLibA.a
,然后是LibB.o
,就像1999年一样(虽然文档说不工作,但似乎到)。(对于我的简单测试项目来说,这些都不是太糟糕,但在现实生活中,这不是一个开源项目,LibA实际上是来自3个不同项目的80个不同的库,而且一些LibA代码构建了胖armv7 / armv7s(这意味着ranlib
无法正常工作......),我们计划将模拟器和本机构建一起进行唇形化,并用它们构建一个框架,所有这些都是使问题更加严重。
答案 0 :(得分:3)
我想我可能用单对象prelink解决了它(基本上这意味着它会建立一个巨大的目标文件ld -r
,然后将其传递给libtool
),尽管我还是不确定,我不喜欢这个解决方案。所以,我会发布我所得到的答案,但希望其他人能得到更好的答案。
要使单对象预链接起作用,您需要(在LibB
中):
libLibA.a
添加为框架。${PROJECT_DIR}/libLibA.a
(第二步是我之前做错了...)
不幸的是,这似乎完全打破了依赖规则,因此即使没有任何更改,每个构建都会重新编译目标中的每个.m(和.pch)。
除了那种烦恼之外,这似乎对AppC
和我的真实项目都很有用。
AppC
不需要“保留私有外部符号”;我的真实项目呢。我相信这是因为其中一个第三方库明确地ld -r
使用空-exported_symbols_list
来“将所有符号转换为private_extern
。否则,类对象不会结束但是,我并不是100%肯定我理解这个。
答案 1 :(得分:0)
将其添加到Other Linker Flags
似乎可行
-force_load $(CONFIGURATION_BUILD_DIR)/libLibA.a