7

我有一个很大的静态库,我想打包成一个 iOS 静态框架以便于使用。该库实际上是几个.a文件,每个库的逻辑模块一个。

.a有为设备(带有armv7, armv7s,arm64的胖文件)和模拟器(带有i386,的胖文件)构建的编译文件x86_64

现在,AFAIK,我需要将所有这些文件合并到一个大文件中,以构建一个合适的框架。

使用此处描述的技术(组合静态库),我可以这样做:

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

但显然两者都old1.a包含old2.a相同的符号。因此,当链接到我的框架时,我得到链接器错误(出于正当理由)duplicate symbols

一种更正确的方法(从而避免重复符号)似乎是解压缩.o文件,并将它们组合成一个大.a文件(如何将多个库存档(.a)打包到一个存档文件中?

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

现在,请记住,old1.a并且old2.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显示了所有符号)。

知道如何构建该静态框架吗?

4

2 回答 2

2

您可以将静态库对象预链接到一个中,也可以将其他静态库预链接到一个中。它实际上会将对象与链接器链接(几乎就像在动态库中一样)。

  1. 在您的单个库(主要库)中,转到 Build Settings 并在 Linking 部分中找到 Perform Single-Object Prelink。将其切换为是
  2. 在 Prelink 库中,您可以指定要包含的其他库。在那里,您不仅需要输入名称,还需要输入完整的文件名。如果其他库也来自您的项目,那么您可以使用 $(CONFIGURATION_BUILD_DIR) 变量。所以如果你有库 foo,那么它将是 $(CONFIGURATION_BUILD_DIR)/libfoo.a
  3. 您可以在 Single-Object Prelink Flags 中添加其他标志
  4. 如果要去除本地符号,请确保将部署后处理设置为是,因为默认情况下不会去除静态库。

如果你的库有重复的符号,那么你的模块结构有问题。

于 2014-02-06T12:17:17.020 回答
1

libtool 真的是在创建胖库吗?我们做一些类似的事情,但直接使用“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。

在创建 target.a 之前,我们通过重命名每个 .o 并给它一个前缀 a_foo.o 来修复它。

于 2014-01-14T01:28:59.873 回答