一、编译原因
公司项目需要,故编译安卓系统的boost库1.66.0。最开始考虑到原有boost版本,采用NDK16b中gcc编译器先后编译了armv7、armv8a架构下的boost。但在随后的Android Studio界面开发中,编译的boost库在编译器链接时无法找到引用unreference。网上查询很多解决方法,发现这个坑根本原因是编译器及采用C++标准库不一致导致。主要因集成开发环境AS中只能采用最新版NDK19c,默认编译器为clang,而本人用NDK16b的GCC编译,导致前功尽弃无法使用。故这里说明一下。
关于NDK采用编译器介绍如下:"Android NDK 在 r17 中宣称不再支持 GCC 并在后续的 r18 中删掉 GCC,并转向Clang和llvm。随着 Android P 的逐步应用,越来越多的客户要求编译库时用 libc++ 来代替 libstdc++。libc++ 和 libstdc++ 这两个库有关系呢?它们两个都是 C++ 标准库,libc++ 是针对 Clang 编译器特别重写的 C++ 标准库,而 libstdc++ 则是 GCC 的对应 C++ 标准库了。"
二、交叉编译环境
CentOS7 NDK19c编译boost1.66.0库,编译目标arm64-v8a以及armeabi-v7a,anroid7.0
Boost下载地址:https://dl.bintray.com/boostorg/release/
NDK下载看我的另一篇博客:https://blog.csdn.net/turbock/article/details/90287035
目前网上采用NDK中clang进行交叉编译的文章很少,故留笔记录。因为boost库默认采用bjam自动化编译器,所以需要修改指定的配置文件。特别说明的是,个人感觉采用哪种平台linux 或 windows或MACOS平台进行交叉编译都不影响,只要下载指定平台对应的NDK包即可,关键还是配置project-config.jam中采用编译器的路径,引用头文件路径及sysroot路径。如采用 linux 64位 进行NDK编译,需要安装包库支持32位开发的包库。CentOS命令:sudo yum install xulrunner.i686 或者: sudo yum install ia32-libs.i686
三、编译boost主要流程
1.下载解压缩boost以及ndk
2.进入boost_1_65_0目录执行./bootstrap.sh生成编译工具,这里会产生b2可执行文件。如果之前编译过其他架构,删除其中缓存目录bin.v2,并执行./b2 clean;
3.覆盖原有project-config.jam文件,编译不同架构的库arm64-v8a、armeabi-v7a将在这里配置,也是重点!!将在随后说明
4.目录中执行./b2 --with-system --with-serialization link=static threading=multi toolset=gcc architecture=arm target-os=android --stagedir=android_build --prefix=android_build
命令行解释:--stagedir=android_build --prefix=android_build,这行命令测试中使用,只编译几个库便于查问题; toolset表示指定编译工具;link=static表示编译成静态库,动态库将static换为shared;threading表示使用多线程编译;--stagedir和--prefix表示指定编译文件生成目录名。--with-system --with-serialization 为指定要编译的库,不指定则默认编译所有库。如果不编译某模块而其他都编译,则只加入 --without-XXX即可,例如--without-python。如果当前编译环境中并没有安装python,建议加入--without-python。
重点:需要注意的是,虽然计划采用NDK19c中的clang编译器编译出arm64架构的库,但boost库内置bjam自动编译脚本工具无法直接识别的,故需要指定toolset=gcc进行伪装兼容,才能适配编译出arm64的库。而在project-config.jam配置中指定编译器的路径才是真正兼容aarch64-linux-android24-clang++脚本,并实际采用了clang编译器;参数architecture=arm target-os=android指定architecture为arm平台,目标操作系统为android;
5.执行安装./b2 install, 其中install 表示安装到前面指定安装目录下面,会拷贝头文件到include。
6.等待编译完成即可,编译完成后可以在当前路径的android_build目录下找到编译完的库文件。Linux下可以采用objdump –h libboost_system.a查看编译位数是否正确。elf64-little表示编译的为arm64-v8a架构64位,elf32-little表示armeabi-v7a架构32位。
四、project-config.jam文件配置
重点注意字段为标红字段。ANDROID_NDK表示NDK根目录,-I表示引入头文件路径,--sysroot路径指定ndk19与ndk16已经不一样了。using gcc后面为指定编译器路径,打开aarch64-linux-android24-clang++ 文件可以发现是脚本文件,重定向到真正的clang++编译器,可能NDK修订时考虑到兼容性因此做的封装。android24表示编译目标系统平台,查看对应安卓系统版本号指定可以参考本人NDK下载博客。
4.1 arm64-v8a架构的配置文件
# Boost.Build Configuration
# Automatically generated by bootstrap.sh
import option ;
import os ;
# Compiler configuration. This definition will be used unless
# you already have defined some toolsets in your user-config.jam
# file.
if [ os.name ] = CYGWIN || [ os.name ] = NT {
androidPlatform = windows-x86_64 ;
}
else if [ os.name ] = LINUX {
androidPlatform = linux-x86_64 ;
#androidPlatform = linux-x86 ;
}
else if [ os.name ] = MACOSX {
androidPlatform = darwin-x86 ;
}
modules.poke : NO_BZIP2 : 1 ;
ANDROID_NDK = /android-ndk-r19c ;
using gcc : android4.9 : $(ANDROID_NDK)/toolchains/llvm/prebuilt/$(androidPlatform)/bin/aarch64-linux-android24-clang++ :
<archiver>$(ANDROID_NDK)/toolchains/llvm/prebuilt/$(androidPlatform)/bin/aarch64-linux-android-ar
<ranlib>$(ANDROID_NDK)/toolchains/llvm/prebuilt/$(androidPlatform)/bin/aarch64-linux-android-ranlib
<compileflags>--sysroot=$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot
<compileflags>-I$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/
<compileflags>-I$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/aarch64-linux-android/
<compileflags>-DNDEBUG
<compileflags>-DBOOST_FILESYSTEM_VERSION=3
<compileflags>-std=c++11
<compileflags>-lc++_static
<compileflags>-fno-addrsig
<compileflags>-O2
<compileflags>-D__ANDROID_API__=24
;
4.2 armeabi-v7a架构
import option ;
import os ;
if [ os.name ] = CYGWIN || [ os.name ] = NT {
androidPlatform = windows-x86_64 ;
}
else if [ os.name ] = LINUX {
androidPlatform = linux-x86_64 ;
#androidPlatform = linux-x86 ;
}
else if [ os.name ] = MACOSX {
androidPlatform = darwin-x86 ;
}
modules.poke : NO_BZIP2 : 1 ;
ANDROID_NDK = /android-ndk-r19c ;
using gcc : android4.9 : $(ANDROID_NDK)/toolchains/llvm/prebuilt/$(androidPlatform)/bin/armv7a-linux-androideabi24-clang++ :
<archiver>$(ANDROID_NDK)/toolchains/llvm/prebuilt/$(androidPlatform)/bin/arm-linux-androideabi-ar
<ranlib>$(ANDROID_NDK)/toolchains/llvm/prebuilt/$(androidPlatform)/bin/arm-linux-androideabi-ranlib
<compileflags>--sysroot=$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot
<compileflags>-I$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/
<compileflags>-I$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/arm-linux-androideabi/
<compileflags>-DNDEBUG
<compileflags>-DBOOST_FILESYSTEM_VERSION=3
<compileflags>-std=c++11
<compileflags>-fno-addrsig
<compileflags>-O2
<compileflags>-D__ANDROID_API__=24
;