📜 ⬆️ ⬇️

Cross compilation of libraries under iOS, doing it right

During the development of a large project, there comes a time when you need to build into the application a library from the open source world with a suitable license. For example, you wanted to speed up the decoding of images, or you needed sqlite3 with fts4, or you need some kind of libicu buns that are not in the system libicucore.

For this, the library you need will need to be built for 5 architectures: armv7, armv7s, arm64, i386, x86_64. There are many pitfalls with cross-compilation that I wouldn’t want to stumble upon when there are already proven solutions. In this short post I will talk about automating the building of libraries using the example of protobuf and sqlite3.

Before we do something, we need to decide what we need at the exit.

Based on these requirements, the following solution was obtained. A makefile that manages downloading, unpacking, patching, and building libraries. Its code is not big, so you can bring it here and discuss it. (Or download c github and run, and then read on. )

We define the path to the newest SDK in the system and in build_arches: run the same Makefile up to arch: with the filled ARCH and IOS_PLATFORM variables. After build_arches: runs, a script will be launched that will collect a fat fat version for each of the libraries.
')
 XCODE_TOOLCHAIN = $(shell xcode-select --print-path)/Toolchains/XcodeDefault.xctoolchain IOS_PLATFORM ?= iphoneos # Pick latest SDK in the directory #IOS_PLATFORM_DEVELOPER = $(shell xcrun -sdk ${IOS_PLATFORM} -show-sdk-platform-path) IOS_SDK = $(shell xcrun -sdk ${IOS_PLATFORM} -show-sdk-path) all: build_arches mkdir -p lib # Make fat libraries for all architectures for file in build/armv7/lib/*.a; \ do name=`basename $$file .a`; \ ${XCODE_TOOLCHAIN}/usr/bin/lipo -create \ -arch armv7 build/armv7/lib/$$name.a \ -arch armv7s build/armv7s/lib/$$name.a \ -arch arm64 build/arm64/lib/$$name.a \ -arch i386 build/i386/lib/$$name.a \ -arch x86_64 build/x86_64/lib/$$name.a \ -output lib/$$name.a \ ; \ done; echo "Making fat libs" # Build separate architectures build_arches: ${MAKE} arch ARCH=armv7 IOS_PLATFORM=iphoneos ${MAKE} arch ARCH=armv7s IOS_PLATFORM=iphoneos ${MAKE} arch ARCH=arm64 IOS_PLATFORM=iphoneos ${MAKE} arch ARCH=i386 IOS_PLATFORM=iphonesimulator ${MAKE} arch ARCH=x86_64 IOS_PLATFORM=iphonesimulator 

When make will work on the dependencies specified in the arch: target, the environment variables will be initialized for the current architecture. Please note that we have filled out PREFIX and the make install libraries will install the build result in the ./build/armv7, ./build/armv7s folders, etc.

Target arch: Indicates the targets on which it depends. In our case, these are the libraries we collect. When adding new libraries, their goals will need to be added to arch: dependencies, otherwise they will not be collected.

 PREFIX = ${CURDIR}/build/${ARCH} LIBDIR = ${PREFIX}/lib INCLUDEDIR = ${PREFIX}/include CXX = ${XCODE_TOOLCHAIN}/usr/bin/clang++ CC = ${XCODE_TOOLCHAIN}/usr/bin/clang CFLAGS = -isysroot ${IOS_SDK} -I${IOS_SDK}/usr/include -arch ${ARCH} -miphoneos-version-min=5.0 CXXFLAGS = -stdlib=libc++ -isysroot ${IOS_SDK} -I${IOS_SDK}/usr/include -arch ${ARCH} -miphoneos-version-min=5.0 LDFLAGS = -stdlib=libc++ -isysroot ${IOS_SDK} -L${LIBDIR} -L${IOS_SDK}/usr/lib -arch ${ARCH} -miphoneos-version-min=5.0 LIBTOOLFLAGS = -arch_only ${ARCH} arch: ${LIBDIR}/libsqlite3.a ${LIBDIR}/libprotobuf.a 

The last part is the simplest. The purpose of building libraries, which depend on the purpose of downloading the source. This is where you can specify custom keys for ./configure or add arm64 support to protobuf.

 ${LIBDIR}/libsqlite3.a: ${CURDIR}/sqlite3 cd sqlite3 && env CXX=${CXX} CC=${CC} CFLAGS="${CFLAGS}" \ CXXFLAGS="${CXXFLAGS} -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS4_UNICODE61" \ LDFLAGS="${LDFLAGS}" ./configure --host=arm-apple-darwin --disable-shared --prefix=${PREFIX} && ${MAKE} clean install ${LIBDIR}/libprotobuf.a: ${CURDIR}/protobuf cd protobuf && env CXX=${CXX} CC=${CC} CFLAGS="${CFLAGS}" CXXFLAGS="${CXXFLAGS}" LDFLAGS="${LDFLAGS}" \ ./configure --host=arm-apple-darwin --disable-shared --with-protoc=/usr/local/bin/protoc --prefix=${PREFIX} && ${MAKE} clean install ${CURDIR}/sqlite3: curl https://www.sqlite.org/2014/sqlite-autoconf-3080403.tar.gz > sqlite3.tar.gz tar xzvf sqlite3.tar.gz rm sqlite3.tar.gz mv sqlite-autoconf-3080403 sqlite3 touch sqlite3 ${CURDIR}/protobuf: curl https://protobuf.googlecode.com/files/protobuf-2.5.0.tar.gz > protobuf.tar.gz tar xzvf protobuf.tar.gz rm protobuf.tar.gz mv protobuf-2.5.0 protobuf # add arm64 support https://code.google.com/p/protobuf/issues/detail?id=575 patch -p0 <protobuf_arm64.patch touch protobuf clean: rm -rf build lib sqlite3 protobuf 

At the output: in the folder / lib are the fat versions of the libraries, and in the build / {$ ARCH} / include header files that may be useful in the work.

Header files for each architecture are not always needed separately, but there are libraries that, at the ./configure stage, explicitly store the sizes of the system types in the header file, for example, in config.h. When we use such a file for arm64 and armv7 at the same time, there is a risk that something will go wrong at some stage of the work. And in order not to guess whether something breaks down in the logic of the library or not and not to include in the project additional library testing on all architectures in search of compatibility problems, I use separate versions of header files for all fat libraries. This is easy to do, in the Header Search Path you need to add "$(SRCROOT)/../../libs/build/$(arch)/include" . Where /../../libs/build/ the build folder relative to the xcodeproj file.

I found this build method in the github repository of the mapnik raster render build , and there you can also see a more complex Makefile option, when one library depends on several others.

Files of this post can be downloaded from github and admire the running lines of cross-compilation. It is enough to type make .

Source: https://habr.com/ru/post/222343/


All Articles