使用Conan将Boost C++库交叉编译到Android
今天,我们在conan-center上发布了一个Conan包 Boost/1.66.0@conan/stable。
此包包含**超过150种不同**配置的二进制文件:Windows(不同版本的Visual Studio)、Linux(gcc和clang编译器)、OSX。在所有系统中,都可以使用不同的体系结构、构建类型,或者选择是否要静态链接、动态链接,甚至使用boost头文件库。
但此包还包含对将boost交叉编译到不同平台(如Raspberry PI或Android)的大量改进。这项出色的工作得益于(conan)社区的许多贡献,感谢大家!!!
Conan-center仅包含最主流的二进制文件,即Windows、Linux和OSX的二进制文件,但这篇文章解释了如何使用conan轻松地将Boost交叉编译到这些平台。
Conan模型
Conan包由配方定义,配方是Python脚本,描述了如何构建和打包库。使用一个Conan配方,可以创建许多不同的二进制包,例如:一个用于Windows Visual Studio 14,另一个用于Linux GCC 6,依此类推。Conan包配方负责翻译用户设置(操作系统、体系结构、编译器等),并使用正确的选项/标志调用底层库的构建系统,为不同的输入设置生成不同的二进制包。
所有平台和配置的包配方和二进制文件都可以上传到同一个Conan服务器,以便与团队共享。从现在开始,如果任何开发人员想要使用此库,并且已经为请求的配置(设置/选项)生成了二进制文件,那么该库将直接从服务器检索。这将为任何开发人员或CI过程节省大量时间,尤其是在我们谈论像boost这样庞大而复杂的库时。
当用户运行“conan install”来检索其项目的依赖项时,Conan将下载配方,使用其设置/选项对其进行评估,并下载与用户配置匹配的二进制文件。
使用Boost Build (b2)交叉编译Boost
Boost构建系统(又名b2)接受一些参数来定义交叉编译
architecture, address-model, binary-format, mfloat-abi, abi, target-os
在我们的例子中,如果我们想交叉编译到Android/ARM系统,传递给“b2”的参数是
architecture=arm
address-model=32
binary-format=elf
abi=appcs
target-os=android
因此,类似的命令将是
$ b2 architecture=arm address-model=32 binary-format=elf
abi=aapcs target-os=android link=static variant=release
--without-python -j8 --abbreviate-paths -d2 --debug-configuration
--build-dir=”my_build_folder"
但这还不够,因为boost有一些第三方依赖项,如zlib或bzip2。用户还需要设置一些环境配置,构建工具和编译器路径,工具链和编译标志的详细信息必须指定。最好的方法是定义一个包含交叉编译详细信息的user-config.jam
文件,它可能如下所示
using zlib : 1.2.11 : <include>/.conan/data/zlib/1.2.11/conan/stable/package/39a53587004d75943e385925ca011baeab537de0/include
<search>/.conan/data/zlib/1.2.11/conan/stable/package/39a53587004d75943e385925ca011baeab537de0/lib ;
using clang : 5 : "arm-linux-androideabi-clang++" :
<archiver>"/path/to/arm_21_toolchain/bin/arm-linux-androideabi-ar"
<ranlib>"/path/to//arm_21_toolchain/bin/arm-linux-androideabi-ranlib"
<cxxflags>"-fPIC -I/path/to/arm_21_toolchain/include/c++/4.9.x"
<cflags>"-fPIC -I/path/to/arm_21_toolchain/include/c++/4.9.x" <ldflags>"" ;
这是一个重要的细节,如果我们想为Android交叉编译Boost,它应该针对我们正在交叉编译Boost的相同配置的zlib和bzip2的交叉编译版本进行链接。
这对任何开发人员来说都可能是一个巨大的挑战,也是一个真正的障碍。幸运的是,conan-center存储库已经包含了zlib和bzip2包,其中包含数百种配置的预构建二进制文件,但最重要的是:它们也知道如何使用自己的构建系统进行交叉编译。
创建包含本地和交叉构建二进制文件的Boost包
有两种创建二进制包的方法。第一种是使用“conan create”,通常由包创建者在上传包之前显式构建和测试包。此过程通常从克隆包含conan包配方的存储库开始
$ git clone -b release/1.66.0 https://github.com/lasote/conan-boost
$ conan create . myuser/testing
第二种方法是使用现有的包。最终用户可以创建一个conanfile.txt
或conanfile.py
,声明必要的包依赖项,然后使用命令“conan install”(更多信息请参见入门)。
一个用于使用boost库的conanfile.txt如下所示
[requires]
boost/1.66.0@conan/stable
“conan install”命令将尝试为开发人员的默认配置下载预构建的二进制包(更多信息请参见默认配置文件),但如果请求的配置没有二进制文件,则可能会失败。在这种情况下,应使用“–build missing”参数强制conan从源代码使用库配方构建库。命令应该是
$ conan install . --build missing
在这两种情况下,要指定要构建哪个配置,使用配置文件非常方便
$ conan install . --build missing --profile my_clang_profile
配置文件是纯文本文件,定义了设置、选项、环境变量和构建要求。
OSX的默认配置文件可能是
[settings]
os=Macos
os_build=Macos
arch=x86_64
arch_build=x86_64
compiler=apple-clang
compiler.version=9.0
compiler.libcxx=libc++
build_type=Release
[options]
[build_requires]
[env]
如果我们想从Windows交叉编译到Raspberry PI,我们可以安装正确的工具链并定义以下配置文件
~/.conan/profiles/rpi
target_host=arm-linux-gnueabihf
standalone_toolchain=C:/sysgcc/raspberry
cc_compiler=gcc
cxx_compiler=g++
[settings]
os_build=Windows
arch_build=x86_64
os=Linux
arch=armv7 # Change to armv6 if you are using Raspberry 1
compiler=gcc
compiler.version=6
compiler.libcxx=libstdc++11
build_type=Release
[env]
CONAN_CMAKE_FIND_ROOT_PATH=$standalone_toolchain/$target_host/sysroot
PATH=[$standalone_toolchain/bin]
CHOST=$target_host
AR=$target_host-ar
AS=$target_host-as
RANLIB=$target_host-ranlib
LD=$target_host-ld
STRIP=$target_host-strip
CC=$target_host-$cc_compiler
CXX=$target_host-$cxx_compiler
CXXFLAGS=-I"$standalone_toolchain/$target_host/lib/include"
并使用此配置文件与conan create一起使用,它将在本地缓存中构建库,并使用我们配置文件“rpi”中指定的设置。
$ conan create . conan/stable --profile=rpi
您可以参考conan文档中的本指南,以了解有关为Raspberry PI编译的更多信息。
如果要交叉构建Conan包,则需要
- 正确的工具链(编译器和工具)
- 一个描述设置和查找工具链所需的环境变量的配置文件。
为Android创建Boost包
准备Android工具链
Android工具链可以从Android NDK生成。
从NDK版本r16开始,仅支持“clang”编译器和“libc++”作为标准c++库。
您可以下载NDK并调用“make_standalone_toolchain.py”脚本,指定api级别、体系结构和标准库
$ cd build/tools
$ python make_standalone_toolchain.py --arch=arm --api=21 --stl=libc++ --install-dir=/myfolder/arm_21_toolchain
准备Conan配置文件
将此配置文件复制并粘贴到您的配置文件文件夹(~/.conan/profiles)中,调整到新的独立工具链的路径(将“/myfolder/arm_21_toolchain”替换为您的安装路径)
.conan/profiles/android_21_armeabi-v7a_clang
standalone_toolchain=/myfolder/arm_21_toolchain
target_host=arm-linux-androideabi
cc_compiler=clang
cxx_compiler=clang++
[settings]
compiler=clang
compiler.version=5.0
compiler.libcxx=libc++
os=Android
os.api_level=21
arch=armv7
build_type=Release
[env]
CONAN_CMAKE_FIND_ROOT_PATH=$standalone_toolchain/sysroot
PATH=[$standalone_toolchain/bin]
CHOST=$target_host
AR=$target_host-ar
AS=$target_host-as
RANLIB=$target_host-ranlib
CC=$target_host-$cc_compiler
CXX=$target_host-$cxx_compiler
LD=$target_host-ld
STRIP=$target_host-strip
CFLAGS= -fPIC -I$standalone_toolchain/include/c++/4.9.x
CXXFLAGS= -fPIC -I$standalone_toolchain/include/c++/4.9.x
LDFLAGS=
为Android构建Boost包
在conan-center中,您可以找到针对已知平台(如Windows、OSX和Linux)的二进制文件,但没有针对Android的二进制文件。在本节中,我们将为Android构建boost,并将生成的包上传到存储库,以便其他开发人员使用,而无需在过程中再次从源代码构建boost库。
我们将使用“conan create”命令,因此我们需要克隆配方存储库
git clone -b release/1.66.0 https://github.com/lasote/conan-boost
conan create . conan/stable --build missing --profile=android_21_armeabi-v7_clang
使用“–build missing”参数,我们告诉conan从源代码构建指定配置文件的任何传递依赖项,在这种情况下,Conan也将交叉构建zlib和bzip2。
现在,我们可以将生成的二进制包上传到conan-server、Artifactory或Bintray。请查看文档中的上传包部分。
> conan upload boost/1.66.0@conan/stable --all -r=myremote
> conan upload zlib* --all -r=myremote
> conan upload bzip2* --all -r=myremote
# or just
> conan upload * --all -r=myremote
我们还可以使用conan config install命令在团队之间共享配置文件、远程连接和设置。
此时,Android的二进制包位于my-remote(即conan-center)中,使用上述配置文件的开发人员可以重用它们,而无需从源代码构建整个boost库。
在**后续的博文中**,我们将使用boost库创建一个Android应用程序,使用Android Studio项目和一个简单的“conanfile.txt”。我们将解释如何为多个架构(arm、x86等)构建相同的应用程序,并将所有内容打包到一个apk中。