Cross-compile to static lib (libgcrypt) for use on iOS

血红的双手。 提交于 2019-11-29 04:33:21

Note that it is not possible to build a universal library that will work for both the iOS Simulator and macOS. iOS/Intel and macOS/Intel are not ABI compatible above the C runtime library (Libc). This answer serves to show you how to crosscompile autoconf based projects for iOS targets, and you can easily lipo the resulting static archives together.

You will want to do something like this:

#!/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

I just threw that script together and verified it works (with the addition of --disable-libpng and skipping tests) for pixman. You will probably need to customize it for libgcrypt, but it serves to show the general pattern for building autoconf/automake/glibtool based projects for iOS.

After building, you'll have content in ~/{DEVICE_ARM{,64},SIM_{i386,x86_64}} and you can either lipo the static libraries together or just use all of them in your project (the linker will emit warnings about missing slices for the "other" archives which you can ignore).

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

Jeremy gave a good answer, but I'd like to add a few things and offer my two cents.

The updated script

#!/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

The iOS toolchain is separated by SDKs and iphonesimulator has a separate SDK as does macos, tvos, and of course iphoneos. For each SDK you'll need one compile. You can lipo together iphonesimulator and iphoneos output into a single library since they contain different architectures, but really they are not compiled with the same SDK. I recommend against the super binary of mixed SDKs.

Why am I doing this?

If you're compiling a library and need this, it is because the library is using autoconf, or in the case of Boost and OpenSSL other custom build systems. The keys to compiling for the SDKs are the correct clang, -sysroot, -miphoneos-ver-min, and -arch flags. If you get the -arch or -sysroot flags wrong you'll see #error Unsupported architecture errors.

Remove the --disable-shared flag

I like leaving the generation of the shared libs even if I intend to use the static library. This generally means you'll compile with Position Independent Code (-fPIC) so if you decide to include this library in a shared library, you're good to go. Also, unlike a static library which isn't linked, but archived, the linking of the shared library often exposes missing objects.

Multiple architectures on the line

You can pass multiple -arch flags on the line and you'll get FAT binaries. This save you some hassle and time during compilation.

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

Remove architectures

In all honesty, do you need i386 support? If you're not targeting that device then don't include the architecture. You only need i386 if your host system runs an OS predating Lion.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!