将2个静态库链接为1,用于iOS

时间:2012-03-02 09:42:37

标签: ios xcode

我在Xcode中创建了两个独立的静态库,用于iOS,A和B.A使用B中定义的方法。

在创建需要A和B的新Xcode项目时,我可以单独包含它们。但是,为了简化集成,我更喜欢创建一个包含A和B的通用框架。

Xcode中是否可以将2个静态库合并为1,而无需合并1个项目中2个库的代码。换一种说法。在编译/链接静态库A时,我可以以某种方式将已编译的静态库B链接到静态库A中吗?

如果可以,我该如何做到这一点?

2 个答案:

答案 0 :(得分:3)

我刚刚进行了一些快速测试,似乎是自动发生的。这就是我所做的:

  • 我使用 DerivedData 文件夹作为所有3个项目的默认构建位置(这在我使用的XCode 4.2中是默认的)
  • 我将公共标题文件夹路径更改为 include / ProjectX ,其中X是静态库的名称。我只为静态库A和B执行此步骤,而不是实际链接它们的项目。此步骤可以导入标题<LibX/Header.h>
  • 我使库B直接依赖库A并将A链接到B
  • 我使图书馆成为主要项目的直接依赖项,并将主要项目与A
  • 相关联

在这个基本设置之后,我将类从B导入到类似于<LibB/Header.h>的类,并编写了一些实际使用了B的代码。然后,我用{{1将A和B导入到主项目中并编写了使用A和B的代码。最后,我使用终端转到 DerivedData 文件夹并导航到构建A的位置。我检查了LibA.a是否包含来自LibB的对象:

<LibA/Header.h>

是的,它包含来自LibB的对象。总而言之,通过这种简单的依赖设置,您应该能够得到您所要求的内容。

修改 为了使B与A的直接相关性和对B的链接A做到这一点:

在XCode中打开,转到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.然后重新打开A并使用Finder导航到B项目文件,然后将B拖放到A工作区内。如果不起作用,请重复。

<强> EDIT2 我的情况是你无法访问B的源(可能还有A),这使得这项工作只需要在适当的位置复制所需的标题。然后在你的主项目中,你没有直接依赖,而是链接到你拥有的静态libA.a。如果A使用B,那么B中的符号已经在libA.a中。你可以像我上面的 nm 工具一样检查这个。因此,我们将使用B头将这些符号暴露给主应用程序。有几种方法可以做到这一点,我记得我只是将标题复制到依赖链中间的库的复制标题目标路径。之后,通过链接A并将A标题添加到用户标题搜索路径,我可以直接访问B.为您做这件事的最佳方式取决于您是否可以访问A的来源。如果有,有两种选择:

  • 将B标头添加到A(它们将自动复制到A标头目的地)。但我想你不想要这个解决方案。
  • 将自定义运行脚本构建阶段添加到目标,该目标将获取B标头并将其复制到A标头目标。

在这两种情况下,最终都会得到包含A和B编译源的LibA.a,以及包含A和B标题的headers文件夹。然后,您可以再次链接主项目LibA.a并添加标题您的主项目中用户标题搜索路径的文件夹路径,您应该很高兴。

重要

如果您的图书馆中包含仅包含类别代码的文件,请务必使用 -force_load 链接此库,否则您的类别符号将无法正确打包。

答案 1 :(得分:2)

我已经使用libtool完成了它,根据this answer

为此,在Xcode 5.0.2中,我向A(Editor -> Add Build Phase -> Add Run Script Build Phase)添加了一个脚本

  • 计算出正在构建A的架构:

    LIPO_ARCH=$(lipo -info ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_NAME} | awk 'END{ print $NF }')
    
  • 创建B的精简版本,只构建正在构建的架构

    lipo -thin ${LIPO_ARCH} ${FULLPATH_OF_B} -output ${FULLPATH_OF_THIN_B}
    
  • 将A和B加入新的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}
    
  • 删除临时文件

    rm ${FULLPATH_OF_THIN_A}
    rm ${FULLPATH_OF_THIN_B}