什么是 NDK?
Android NDK 是一套可以让开发者在安卓应用开发中使用 C/C++ 实现特定模块的工具集,不是所有应用都需要用到,但是正确地使用可以有效提高应用运行效率和安全性。
硬件体系:
因为安卓的app可能运行在armv7 或者armv8上,所以针对每个运行的平台都需要导出对应的交叉编译工具链。
其中一些基本的体系架构需要了解,armv7体系是32位的arm,armv8为64位或32位的arm,其中arm64对应的交叉编译工具链位。
获取NDK:
首先上官方文档
https://developer.android.com/ndk/guides/standalone_toolchain.html
可以自定义工具链进行交叉编译
NDK导出交叉编译工具链:
因为我们的安卓程序运行在armv7 核armv8上,分别导出交叉编译工具链
armv7:
export NDK_HOME=/workspace/android-ndk-r10e
$NDK_HOME/build/tools/make-standalone-toolchain.sh --arch=arm --platform=android-21 --install-dir=$HOME/android-toolchain --toolchain=arm-linux-androideabi-4.9
armv8:
export NDK_HOME=/workspace/android-ndk-r10e
$NDK_HOME/build/tools/make-standalone-toolchain.sh --arch=arm64 --platform=android-21 --install-dir=$HOME/android-toolchain --toolchain=aarch64-linux-androideabi-4.9
编译动态库:
有些开源的动态库编译完有soname。
$objdump -p libssl.so | grep SONAME
SONAME libssl.so.1.1
如:libssl.so.1.1,但安卓ide不识别此动态库,需要去掉动态库里面的soname,目前有两种方法,一种直接修改开源库的编译配置文件,此方法比较麻烦,另一种是利用工具patchelf
方法1:
对于Android来说,我们更希望编译之后 so 本身名字就叫 libssl.so。
具体做法是解压 openssl-1.1.1o.tar.gz 之后,修改 15-android.conf
大概 193 行
my %targets = (
"android" => {
inherit_from => [ "linux-generic32" ],
template => 1,
################################################################
# Special note about -pie. The underlying reason is that
# Lollipop refuses to run non-PIE. But what about older systems
# and NDKs? -fPIC was never problem, so the only concern is -pie.
# Older toolchains, e.g. r4, appear to handle it and binaries
# turn out mostly functional. "Mostly" means that oldest
# Androids, such as Froyo, fail to handle executable, but newer
# systems are perfectly capable of executing binaries targeting
# Froyo. Keep in mind that in the nutshell Android builds are
# about JNI, i.e. shared libraries, not applications.
cflags => add(sub { android_ndk()->{cflags} }),
cppflags => add(sub { android_ndk()->{cppflags} }),
cxxflags => add(sub { android_ndk()->{cflags} }),
bn_ops => sub { android_ndk()->{bn_ops} },
bin_cflags => "-pie",
enable => [ ],
shared_extension => ".so", ### 这一行是新加的
},
这样可以编译出来不带版本后缀的 libssl.so 和 libcrypto.so
方法2:
patchelf --set-soname libssl.so.1.1 libssl.so
官方指导文档:
https://developer.android.com/ndk/guides/standalone_toolchain.html