交叉编译到静态库(libgcrypt)以在iOS上使用

时间:2014-11-07 23:58:24

标签: ios autoconf libgcrypt

我已经下载了最新的libgcrypt&来自https://www.gnupg.org/download/index.html的libgpg错误库。我已经使用./configure --enable-static --disable-shared成功构建了(命令行)两个库。制作在我的Mac上安装make(Mavericks w / OSX 10.10和最新的Xcode 6.1)。

我可以从我正在构建的OS X客户端应用程序链接到这些新库。到现在为止还挺好。刚刚好。但是,我还需要使用相同的源代码构建iOS客户端。

问题:

1)对于我需要为(模拟器,Mac和iOS)构建通用静态库所需的库的命令行构建序列有哪些修改? 2)或者我是否需要为iOS构建单独的静态库?如果是这样,那么,我需要使用什么命令行魔法才能完成目标架构?

2 个答案:

答案 0 :(得分:12)

请注意,无法构建适用于iOS模拟器和macOS的通用库。 iOS / Intel和macOS / Intel在C运行时库(Libc)之上不兼容ABI。这个答案用于向您展示如何为iOS目标交叉编译基于autoconf的项目,并且您可以轻松地将生成的静态档案压缩在一起。

你会想做这样的事情:

#!/bin/bash -e -x

OPT_FLAGS="-Os -g3"
MAKE_JOBS=16

dobuild() {
    export CC="$(xcrun -find -sdk ${SDK} cc)"
    export CXX="$(xcrun -find -sdk ${SDK} cxx)"
    export CPP="$(xcrun -find -sdk ${SDK} cpp)"
    export CFLAGS="${HOST_FLAGS} ${OPT_FLAGS}"
    export CXXFLAGS="${HOST_FLAGS} ${OPT_FLAGS}"
    export LDFLAGS="${HOST_FLAGS}"

    ./configure --host=${CHOST} --prefix=${PREFIX} --enable-static --disable-shared

    make clean
    make -j${MAKE_JOBS}
    make install
}

SDK="iphoneos"
ARCH_FLAGS="-arch armv7"
HOST_FLAGS="${ARCH_FLAGS} -miphoneos-version-min=8.0 -isysroot $(xcrun -sdk ${SDK} --show-sdk-path)"
CHOST="arm-apple-darwin"
PREFIX="${HOME}/DEVICE_ARM"
dobuild

SDK="iphoneos"
ARCH_FLAGS="-arch arm64"
HOST_FLAGS="${ARCH_FLAGS} -miphoneos-version-min=8.0 -isysroot $(xcrun -sdk ${SDK} --show-sdk-path)"
CHOST="arm-apple-darwin"
PREFIX="${HOME}/DEVICE_ARM64"
dobuild

SDK="iphonesimulator"
ARCH_FLAGS="-arch i386"
HOST_FLAGS="${ARCH_FLAGS} -mios-simulator-version-min=8.0 -isysroot $(xcrun -sdk ${SDK} --show-sdk-path)"
CHOST="i386-apple-darwin"
PREFIX="${HOME}/SIM_i386"
dobuild

SDK="iphonesimulator"
ARCH_FLAGS="-arch x86_64"
HOST_FLAGS="${ARCH_FLAGS} -mios-simulator-version-min=8.0 -isysroot $(xcrun -sdk ${SDK} --show-sdk-path)"
CHOST="x86_64-apple-darwin"
PREFIX="${HOME}/SIM_x86_64"
dobuild

我只是将该脚本放在一起并验证它是否有效(对于pixman添加了--disable-libpng和跳过测试)。您可能需要为libgcrypt自定义它,但它用于显示为iOS构建基于autoconf / automake / glibtool的项目的一般模式。

构建完成后,您将拥有〜/ {DEVICE_ARM {,64},SIM_ {i386,x86_64}}中的内容,您可以将静态库集中在一起,也可以在项目中使用所有这些内容(链接器将发出有关您可以忽略的其他"存档的缺失切片的警告。

lipo -create -output lib.a DEVICE_ARM/lib/lib.a DEVICE_ARM64/lib/lib.a SIM_i386/lib/lib.a SIM_x86_64/lib/lib.a

答案 1 :(得分:1)

Jeremy给出了一个很好的答案,但我想补充一些东西并提供我的两分钱。

更新的脚本

#!/bin/bash

OPT_FLAGS="-O3 -g3"
MAKE_JOBS=8

dobuild() {
    export CC
    CC=$(xcrun --find --sdk "${SDK}" gcc)
    export CXX
    CXX=$(xcrun --find --sdk "${SDK}" g++)
    export CPP
    CPP=$(xcrun --find --sdk "${SDK}" cpp)
    export CFLAGS
    CFLAGS="${HOST_FLAGS} ${OPT_FLAGS}"
    export CXXFLAGS
    CXXFLAGS="${HOST_FLAGS} ${OPT_FLAGS}"
    export LDFLAGS
    LDFLAGS="${HOST_FLAGS}"

    ./configure --host="${CHOST}" --prefix="${PREFIX}" --enable-static

    make clean
    make -j"${MAKE_JOBS}"
    make install
}

SDK="iphoneos"
ARCH_FLAGS="-arch armv7 -arch armv7s -arch arm64"
HOST_FLAGS="${ARCH_FLAGS} -miphoneos-version-min=8.0 -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)"
CHOST="arm-apple-darwin"
PREFIX="${HOME}/DEVICE_ARM"
dobuild

SDK="iphonesimulator"
ARCH_FLAGS="-arch x86_64"
HOST_FLAGS="${ARCH_FLAGS} -mios-simulator-version-min=8.0 -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)"
CHOST="x86_64-apple-darwin"
PREFIX="${HOME}/SIM_x86"
dobuild

iOS工具链由SDK分开,iphonesimulator有一个单独的SDK,macos,tvos,当然还有iphoneos。对于每个SDK,您需要一个编译。您可以将iphonesimulator和iphoneos输出组合到一个库中,因为它们包含不同的体系结构,但实际上它们不是使用相同的SDK编译的。我建议不要使用混合SDK的超级二进制文件。

为什么我这样做?

如果您正在编译库并需要它,那是因为库使用的是autoconf,或者在Boost和OpenSSL的情况下使用其他自定义构建系统。编译SDK的关键是正确的clang-sysroot-miphoneos-ver-min-arch标志。如果您的-arch-sysroot标记错误,您会看到#error Unsupported architecture错误。

删除--disable-shared标志

即使我打算使用静态库,我也喜欢离开共享库的生成。这通常意味着您将使用位置独立代码(-fPIC)进行编译,因此如果您决定将此库包含在共享库中,那么您就可以了。此外,与未链接但已归档的静态库不同,共享库的链接通常会暴露丢失的对象。

线路上的多种架构

您可以在该行上传递多个-arch标记,您将获得FAT二进制文件。这可以节省编译过程中的麻烦和时间。

$ lipo -info libwhatever.a 
Architectures in the fat file: libwhatver.a are: i386 x86_64 

删除架构

说实话,你需要i386支持吗?如果您没有定位该设备,则不要包含该体系结构。如果主机系统在Lion之前运行操作系统,则只需要i386。