7

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

我可以从我正在构建的 OS X 客户端应用程序中很好地链接到这些新库。到目前为止,一切都很好。刚刚好。但是,我还需要使用相同的源代码构建一个 iOS 客户端。

问题:

1)我需要为(模拟器,Mac和iOS)构建通用静态库的库的命令行构建序列有哪些修改?2) 还是我需要为 iOS 构建单独的静态库?如果是这样,我需要什么命令行魔法来完成正确的目标架构?

4

2 回答 2

14

请注意,无法构建适用于 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 或只在项目中使用它们(链接器将发出警告您可以忽略的“其他”档案缺少切片)。

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
于 2014-11-08T00:56:26.097 回答
2

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

更新的脚本

#!/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 和 macos、tvos,当然还有 iphoneos 一样,都有一个单独的 SDK。对于每个 SDK,您都需要进行一次编译。您可以将 iphonesimulator 和 iphoneos 输出合并到一个库中,因为它们包含不同的架构,但实际上它们不是使用相同的 SDK 编译的。我建议不要使用混合 SDK 的超级二进制文件。

我为什么要这样做?

如果您正在编译一个库并且需要它,那是因为该库正在使用 autoconf,或者在 Boost 和 OpenSSL 的情况下使用其他自定义构建系统。为 SDK 编译的关键是正确clang的 、-sysroot-miphoneos-ver-min-arch标志。如果你弄错了-archor-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。

于 2018-04-29T06:43:01.797 回答