当创建一个需要同时使用A和B的新的Xcode项目时,我可以单独包含它们。然而,为了简化集成,我更喜欢创建一个包含A和B的通用框架。
在Xcode中,是否有可能将2个静态库合并成1个,而不将2个库的代码合并到1个项目中?换句话说,我能否在编译/链接静态库A时将编译好的静态库B链接到静态库A中?
如果这是可能的,我该如何实现?
<LibX/Header.h>
这样导入头文件。<LibB/Header.h>
的方式从B导入类到A,并编写了一些实际使用B的代码。然后,我使用<LibA/Header.h>
和<LibB/Header.h>
将A和B导入到主项目中,并编写了使用A和B的代码。最后,我通过终端进入了DerivedData文件夹,并导航到构建A的位置。我使用以下命令检查LibA.a文件是否包含来自LibB的对象:nm LibA.a
是的,它包含来自LibB的对象。因此,总结一下,通过这个简单的依赖设置,您应该能够得到您所要求的。
编辑 要使B成为A的直接依赖项并将A链接到B,请执行以下操作:
在XCode中打开A,转到Finder并将B项目文件拖放到A中。然后,在A中选择根元素,转到Build Phases,展开Target Dependencies,按“+”按钮,选择B并确认。然后展开Link Binary With Libraries,按“+”按钮,选择B.a(或任何产品名称)并确认。
重要提示 XCode中存在一个错误,会导致您无法正确地将B项目文件拖放到A工作区。相反,您将在A工作区中留下B项目文件,但是您无法扩展B并对其进行任何操作。要解决此问题,请从A中删除有问题的B项目文件引用,关闭A,如果您已经打开B,则关闭B。然后重新打开A,并使用Finder导航到B项目文件,然后将B拖放到A工作区内。如果不起作用,请重复上述步骤。
编辑2 如果您没有访问B(可能还包括A)的源代码,则使之工作只是将所需的标头复制到正确的位置。然后在主项目中,您不会将A作为直接依赖项,而是链接到您拥有的静态libA.a。如果A使用B,则来自B的符号已经在libA.a中了。您可以使用nm工具检查此情况,就像我以上所做的那样。因此,我们只需要使用B标头将这些符号公开给主应用程序。有几种方法可以实现这一点,我记得我只是将标头复制到依赖链中间的库的Copy Headers目标路径中。之后,通过链接A并将A标头添加到User Header Search Paths中,我就能够直接访问B了。最适合您的方法取决于您是否可以访问A的源代码。如果您有,有两个选项可供考虑:
在这两种情况下,您最终都会得到LibA.a,其中包含了A和B的编译源代码,以及包含A和B标头的标头文件夹。然后,您可以将您的主项目链接到LibA.a,并将标头文件夹路径添加到User Headers Search Path中,然后您应该就可以开始了。
重要提示
如果在您的库中有仅包含类别代码的文件,请确保使用-force_load链接此库,否则您的类别符号将无法正确打包。
我已经用libtool完成了它,按照这个答案的建议。
为此,在Xcode 5.0.2中,我向A添加了一个脚本(Editor -> Add Build Phase -> Add Run Script Build Phase
),其中包括:
figures out the architecture for which A is being built:
LIPO_ARCH=$(lipo -info ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_NAME} | awk 'END{ print $NF }')
creates a thin version of B, with only the architecture being built
lipo -thin ${LIPO_ARCH} ${FULLPATH_OF_B} -output ${FULLPATH_OF_THIN_B}
joins A and B into a new A
mv ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_NAME} ${FULLPATH_OF_THIN_A}
libtool -static -o ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_NAME} ${FULLPATH_OF_THIN_A} ${FULLPATH_OF_THIN_B}
removes the temp files
rm ${FULLPATH_OF_THIN_A}
rm ${FULLPATH_OF_THIN_B}