将几个静态库编译成一个iOS框架

8

我有一个巨大的静态库,希望将其打包成iOS静态框架以便于使用。实际上这个库是由几个逻辑模块组成的.a文件。

我已经为设备编译好了.a文件(fat文件包含armv7armv7sarm64),也为模拟器编译好了i386x86_64的fat文件。

现在,据我所知,我需要将所有这些文件合并为一个大文件,以便构建正确的框架。

使用此处描述的技术 (Combine static libraries),我可以做到:

libtool -static -o new.a old1.a old2.a

但是显然old1.aold2.a都包含相同的符号。因此,当链接到我的框架时,我会得到链接器错误(有充分的理由)duplicate symbols

更正确的方法是解压缩.o文件,并将它们组合成一个大的.a文件(如何将多个库归档文件(.a)打包成一个归档文件?),以避免重复的符号。

ar x old1.a
ar x old2.a
ar rcs new.a *.o

现在,请记住,old1.aold2.a是庞大的文件,因此我需要按体系结构进行分离。
所以这是我所做的事情:
lipo old1.a -thin armv7 -output armv7/old1.a
cd armv7; ar x old1.a; cd ..
...
lipo old1.a -thin x86_64 -output x86_64/old1.a
cd x86_64; ar x old1.a; cd ..

// Same goes for old2.a ...

// Then, 
libtool -static -o new.a armv7/*.o armv7s/*.o arm64/*.o // ... etc

但是出于某些原因,当链接到这个创建的框架时,链接器找不到任何符号(即使 nm 显示它们全部存在)。

有没有想法如何构建这个静态框架?


你不能直接从源代码编译库吗?除非你想用符号进行巫术般的操作,否则这可能是最简单的方法。 - SevenBits
嗯,我需要将所有代码编译成一个静态库,这将需要对第三方代码的构建系统进行大量修改。 - Olotiar
2个回答

3
您可以将静态库对象预链接成一个单独的静态库,也可以将其他静态库预链接成一个。它实际上会使用链接器将对象链接在一起(几乎像动态库一样)。
  1. 在您的单个库(主要的库)中,进入“构建设置”并找到“链接”部分的“执行单个对象预链接”。将其切换为“Yes”。
  2. 在预链接库中,您可以指定要包含的其他库。在那里,您需要放置完整的文件名,而不仅仅是名称。如果其他库也来自您的项目,则可以使用$(CONFIGURATION_BUILD_DIR)变量。所以如果您有库foo,那么它将是$(CONFIGURATION_BUILD_DIR)/libfoo.a
  3. 您可以在单个对象预链接标志中添加其他标志。
  4. 如果您想剥离本地符号,请确保将部署后处理设置为Yes,因为默认情况下静态库不会被剥离。

如果您的库具有重复的符号,则说明模块结构存在问题。


你可以躲起来,但你无法变成另一个人!(抱歉,不得不这么说) - Salx

1

libtool是否真的创建了fat库?我们做了类似的事情,但直接使用“lipo -create”

ar -r armv7.a a/armv7/*.o b/armv7/*.o c/armv7/*.o d/armv7/*.o e/armv7/*.o
ar -r armv7s.a a/armv7s/*.o b/armv7s/*.o c/armv7s/*.o d/armv7s/*.o e/armv7s/*.o
ar -r i386.a a/i386/*.o b/i386/*.o c/i386/*.o d/i386/*.o e/i386/*.o


$LIPO \
        -create \
        -arch armv7 "objs/armv7.a" \
        -arch i386  "objs/i386.a" \
        -o "$FRAMEWORK_INSTALL_NAME" \
    || abort "Lipo $1 failed"

我们遇到了一个问题,一个ISV在使用我们的框架时做了相同的事情来创建他们的框架。尽管a/foo.o和b/foo.a可以被正确地放入我们的armv7.o中,但当他们提取“ar -x”时,ar不会保留路径,因此只有一个foo.o会被写入。
我们通过在创建目标.a之前重命名每个.o并给它一个前缀a_foo.o来解决了这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接