首先须要肯定目标机器的指令集。linux
若是是 x86 的机器,用 x86-4.4.3 版本的工具链;若是是 arm 指令的,用 arm-linux-androideabi-4.4.3 版本 (x86-4.4.3 和 arm-linux-androideabi-4.4.3 位于ndk目录中)android
一、gcc 的sysroot 选项c++
sysroot 选项设定 gcc 在编译源码的时候,寻找头文件和库文件的根目录。能够这样调用 gcc --sysroot=/tmp/gcc-arm (及其余选项)。NDK 根目录下的 platforms 目录中的各个子目录的路径均可以直接传给 gcc --sysroot=
$ SYSROOT=$NDK/platforms/android-8/arch-armide
二、调用 NDK gcc(第1种方法)。 设置 SYSROOT以后,要把它传给 gcc 的 --sysroot 选项。因为unix/linux自带的gcc并不是交叉编译工具,而咱们须要使用的是ndk中提供的交叉编译工具(也是gcc),因此须要想办法让编译脚本找到ndk中的gcc,而不要去寻找系统中的gcc。而 unix/linux 系统的编译脚本经常会用 CC 环境变量来引用编译器,因此经过把 CC 设置为ndk中的gcc的路径,就能帮助编译脚本找到正确的gcc(咱们还能顺便加上--sysroot选项)。函数
将CC 按以下设置
工具
$ export CC="$NDK/toolchains//prebuilt//bin/gcc --sysroot=$SYSROOT"ui
$ $CC -o foo.o -c foo.c (没必要执行这一行,这条命令是调用gcc编译程序)编码
上面第1行以后以后,再去执行./configure 就能够编译出arm程序了。不过还须要考虑共享库的连接问题,要确保该程序没有连接ndk未提供的共享库。该方法的缺陷就是,不能使用 C++ STL(STLport 或 GNU libstdc++ ),也不能使用异常机制和RTTI。idea
三、调用NDK编译器(第2种方法,更简单)
android ndk 提供脚本,容许本身定制一套工具链。例如:
$NDK/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain [ --arch=x86 ]
将会在/tmp/my-android-toolchain 中建立 sysroot 环境和 工具链。--arch 选项选择目标程序的指令架构,默认是为 arm。
若是不加 --install-dir 选项,则会建立 /tmp/ndk/.tar.bz2。
(执行 make-standalone-toolchain.sh --help 查看帮助。)
运行以后,这样使用:
$ export PATH=/tmp/my-android-toolchain/bin:$PATH
$ export CC=arm-linux-androideabi-gcc
$ export CXX=arm-linux-androideabi-g++
$ export CXXFLAGS="-lstdc++"
执行完以上设置环境变量的命令以后,就能够直接编译了(例如,执行 ./configure 而后 make 获得的就是 arm 程序了)。不用再设定 sysroot, CC 了。并且,可使用 STL,异常,RTTI。
四、ABI 兼容性
ndk 同时支持 arm5 和 arm7,通常只用 arm5就行了。arm7是高端一点的,NDK 默认也是 arm5 。
推荐加上 -mthumb 选项给gcc,来生成 16-bit Thumb-1 指令。
若是要用 arm7,能够设定 CFLAGS='-march=armv7-a -mfloat-abi=softfp', 使用 Thumb-2 指令,且这两个选项不能分开!
五、警告 & 限制
5.1 Windows支持
Windows 上的NDK 工具链不依赖 Cygwin,于是速度比用 Cygwin 快一点,可是这些工具不能理解
Cygwin 的路径名(例如, /cygdrive/c/foo/bar)。只能理解 C: /cygdrive/c/foo/bar 这类路径
不过,NDK 提供的build工具可以很好地应对上述问题(ndk-build)
5.2 wchar_t 支持
wchar_t 类型仅从 Android 2.3 开始支持。
在 android-9 上, wchar_t 是 4字节。 而且 C语言库提供支持宽字符的函数
(例外:multi-byte 编码/解码 函数 和 wsprintf/wsscanf )
在android-9 之前的平台上,wchar_t 是1字节,并且宽字符函数不起做用。
建议不使用 wchar_t,提供 wchar_t 支持是为了方便移植之前的代码。
5.3 异常, RTTI 和 STL
NDK 工具链默认支持C++异常和RTTI(Run Time Type Information),能够用 -fno-exception 和 -fno-rtti 关闭(生成的机器码更小)
注意: 若是要用这两个特性,须要显式连接 libsupc++。例如: arm-linux-androideabi-g++ .... -lsupc++
NDK 提供了 libstdc++,于是能够用 STL,但须要显式连接 libstdc++ ( gcc ... -lstdc++)。不过在未来能够不用手动指定这个连接参数。