3

Android开发实践:如何设置NDK的编译选项

 3 years ago
source link: http://www.androidchina.net/4922.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Android开发实践:如何设置NDK的编译选项 – Android开发中文站
你的位置:Android开发中文站 > Android开发 > 新手入门 > Android开发实践:如何设置NDK的编译选项

本文是我的《Android NDK开发》系列的又一篇文章,上篇文章中,我分享了一个可以自动添加源文件列表的 Android.mk 示例模板,方便大家快速地搭建起完整的 NDK 开发工程框架,本文则主要探究几个主要的 NDK 编译选项的配置,其中包括:APP_ABI、LOCAL_LDLIBS、LOCAL_CFLAGS、APP_STL 这几项,让你从此不再对 NDK 的编译参数望而生却。

1. 概述

首先回顾一下 Android NDK 开发中,Android.mk 和 Application.mk 各自的职责。

Android.mk,负责配置如下内容:

(1) 模块名(LOCAL_MODULE)

(2) 需要编译的源文件(LOCAL_SRC_FILES)

(3) 依赖的第三方库(LOCAL_STATIC_LIBRARIES,LOCAL_SHARED_LIBRARIES)

(4) 编译/链接选项(LOCAL_LDLIBS、LOCAL_CFLAGS)

Application.mk,负责配置如下内容:

(1) 目标平台的ABI类型(默认值:armeabi)(APP_ABI)

(2) Toolchains(默认值:GCC 4.8)

(3) C++标准库类型(默认值:system)(APP_STL)

(4) release/debug模式(默认值:release)

由此我们可以看到,本文所涉及的编译选项在Android.mk和Application.mk中均有出现,下面我们将一个个详细介绍。

2. APP_ABI

ABI全称是:Application binary interface,即:应用程序二进制接口,它定义了一套规则,允许编译好的二进制目标代码在所有兼容该ABI的操作系统和硬件平台中无需改动就能运行。(具体的定义请参考 百度百科 或者 维基百科 )

由上述定义可以判断,ABI定义了规则,而具体的实现则是由编译器、CPU、操作系统共同来完成的。不同的CPU芯片(如:ARM、Intel x86、MIPS)支持不同的ABI架构,常见的ABI类型包括:armeabi,armeabi-v7a,x86,x86_64,mips,mips64,arm64-v8a等。

这就是为什么我们编译出来的可以运行于Windows的二进制程序不能运行于Mac OS/Linux/Android平台了,因为CPU芯片和操作系统均不相同,支持的ABI类型也不一样,因此无法识别对方的二进制程序。

而我们所说的“交叉编译”的核心原理也跟这些密切相关,交叉编译,就是使用交叉编译工具,在一个平台上编译生成另一个平台上的二进制可执行程序,为什么可以做到?因为交叉编译工具实现了另一个平台所定义的ABI规则。我们在Windows/Linux平台使用Android NDK交叉编译工具来编译出Android平台的库也是这个道理。

这里给出最新 Android NDK 所支持的ABI类型及区别:

那么,如何指定ABI类型呢?在 Application.mk 文件中添加一行即可:

APP_ABI := armeabi-v7a //只编译armeabi-v7a版本
APP_ABI := armeabi armeabi-v7a //同时编译armeabi,armeabi-v7a版本
APP_ABI := all //编译所有版本

3. LOCAL_LDLIBS

Android NDK 除了提供了Bionic libc库,还提供了一些其他的库,可以在 Android.mk 文件中通过如下方式添加依赖:

LOCAL_LDLIBS := -lfoo

其中,如下几个库在 Android NDK 编译时就默认链接了,不需要额外添加在 LOCAL_LDLIBS 中:

(1) Bionic libc库

(2) pthread库(-lpthread)

(3) math(-lmath)

(4) C++ support library (-lstdc++)

下面我列了一个表,给出了可以添加到“LOCAL_LDLIBS”中的不同版本的Android NDK所支持的库:

4. LOCAL_CFLAGS

我们可以在 Android.mk 文件中设置 LOCAL_CFLAGS 来为编译源代码添加额外的编译选项,由于NDK实际上也是调用GCC命令来完成编译和链接的,因此,LOCAL_CFLAGS 的可选参数配置大家可以参考GCC的官方文档,链接如下:

《GCC 4.8.4 Manual》

《GCC Command Options》

下面是我总结的一些常用的CFLAGS编译选项:

(1)通用的编译选项

-O2  编译优化选项,一般选择O2,兼顾了优化程度与目标大小

-Wall  打开所有编译过程中的Warning

-fPIC  编译位置无关的代码,一般用于编译动态库

-shared 编译动态库

-fopenmp 打开多核并行计算,

-Idir 配置头文件搜索路径,如果有多个-I选项,则路径的搜索先后顺序是从左到右的,即在前面的路径会被选搜索

-nostdinc 该选项指示不要标准路径下的搜索头文件,而只搜索-I选项指定的路径和当前路径。

–sysroot=dir 用dir作为头文件和库文件的逻辑根目录,例如,正常情况下,如果编译器在/usr/include搜索头文件,在/usr/lib下搜索库文件,它将用dir/usr/include和dir/usr/lib替代原来的相应路径。

-llibrary 查找名为library的库进行链接

-Ldir 增加-l选项指定的库文件的搜索路径,即编译器会到dir路径下搜索-l指定的库文件。

-nostdlib 该选项指示链接的时候不要使用标准路径下的库文件

(2) ARM平台相关的编译选项

-marm -mthumb 二选一,指定编译thumb指令集还是arm指令集

-march=name  指定特定的ARM架构,常用的包括:-march=armv6, -march=armv7-a

-mfpu=name   给出目标平台的浮点运算处理器类型,常用的包括:-mfpu=neon,-mfpu=vfpv3-d16

-mfloat-abi=name 给出目标平台的浮点预算ABI,支持的参数包括:“soft”, “softfp” and “hard”

5. APP_STL

从Android NDK r5 开始支持 STL 了,只需要在 Application.mk 文件中添加对 APP_STL 的定义即可:

APP_STL := gnustl_static

默认情况下,system 库只支持部分 STL 的功能,不支持C++异常,不支持RTTI,不过,NDK 集成了一系列其他的C++运行时库,可以提供这些功能,这些库的特性如下所示:

我们可以通过修改 Application.mk文件中的 APP_STL 来配置到底选择使用哪一种C++支持库:

system         -> Use the default minimal system C++ runtime library.  
gabi++_static  -> Use the GAbi++ runtime as a static library.  
gabi++_shared  -> Use the GAbi++ runtime as a shared library.  
stlport_static  -> Use the STLport runtime as a static library.  
stlport_shared  -> Use the STLport runtime as a shared library.  
gnustl_static   -> Use the GNU STL as a static library.  
gnustl_shared   -> Use the GNU STL as a shared library.

6. 小结

关于如何设置NDK的编译选项就介绍到这儿了,有任何疑问,欢迎留言或者来信[email protected]交流,也可以关注我的新浪微博 @卢_俊 或者微信公众号 @Jhuster 获取最新的文章和资讯。

转载请注明:Android开发中文站 » Android开发实践:如何设置NDK的编译选项


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK