I have downloaded latest libgcrypt & libgpg-error libraries from https://www.gnupg.org/download/index.html. I have successfully built (command line) both libraries using ./configure --enable-static --disable-shared; make ; make install on my Mac (Mavericks w/OSX 10.10 & latest Xcode 6.1).
I can link just fine to these new libs from an OS X client app I am building. So far, so good. Just perfect. BUT, I also need to build an iOS client using same exact source code.
Questions:
1) What are the modifications to the command line build sequence for the library I would need to build a universal static library for the (simulator, Mac & iOS)? 2) Or do I need to build separate static libs for iOS? And if so, again, what command line magic would I need to accomplish getting the target architecture right?
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.
#!/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.
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.
--disable-shared
flagI 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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With