Android平台编译makefile编写规则

1、参考

https://www.ibm.com/developerworks/cn/opensource/os-cn-android-build/
https://blog.csdn.net/yuanjize1996/article/details/54376228
https://blog.csdn.net/xyz_lmn/article/details/6966259/
https://developer.android.google.cn/ndk/guides/stable_apis#purpose

android ndk下载:(内含ndk-build)
https://developer.android.google.cn/ndk/downloads/
http://www.voidcn.com/article/p-fjfskgpc-bph.html

说明:当前最新版本的android-ndk版本是r16b。

Android NDK说明:
主要是包括编译C/C++/ASM代码的编译器,需要按照ndk相关规则进行程序的编译。因此ndk编译器需要编写符合android规则的makefile才能编译。

2、android平台makefile编写方法

http://android.mk/#intro 该网址下面有Android.mk的详细编写方法。

在任意目录执行NDK编译:

2.1 准备环境

首先,你得安装了Android的NDK编译工具,假设你的NDK的根目录在 /opt/android/ndk .
当然,最好你能在环境变量里配置一下路径,否则使用ndk-build命令的时候,都得加上路径的前缀了。

修改 ~/.bashrc

export NDK_HOME=/opt/android/ndk
export PATH=$NDK_HOME:$PATH

然后执行:

$ source ~/.bashrc

2.2 编写 .c 文件

假设你在 ~/math 目录下编写了一个 math.c 文件,内容如下:

#include <stdio.h>

int add( int a , int b ) {
    return a+b;
}

OK,后面我们就准备在 ~/math 目录下,将这个.c文件编译为Android可使用的静态库/动态库了。

2.3 编译成动态库

编写 Android.mk 文件,内容如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := dmath
LOCAL_SRC_FILES := math.c
include $(BUILD_SHARED_LIBRARY)

在 ~/math 目录下,执行 ndk-build 命令,参数如下:

$ ndk-build -B  NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk

其中,NDK_PROJECT_PATH 指定了需要编译的代码的工程目录,这里给出的是当前目录,APP_BUILD_SCRIPT给出的是Android makefile文件的路径,当然,如果你还有 Application.mk 文件的话,则可以添加

NDK_APP_APPLICATION_MK=./Application.mk

执行完ndk-build命令后,你会发现当前目录下,生成了 obj 和 libs 文件夹,这样,你的libdmath.so动态库就已经制作完成了,在 libs/armeabi 目录下。

2.4 编译为静态库

编译为静态库,与编译为动态库唯一的区别就是 Android.mk 文件的写法不同,另外,如果要编译为静态库,则必须有其他的代码引用该静态库代码,ndk-build才会真正执行,否则无法成功生成静态库,这里,我们编写一个 Android.mk ,将 math.c 同时编译成静态库和动态库。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := smath
LOCAL_SRC_FILES := math.c
include $(BUILD_STATIC_LIBRARY)

同样,在 ~/math 目录下执行:

$ ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk

你会在生成的 libs/armeabi 目录下看到动态库libdmath.so,在 obj/local/armeabi 目录下看到静态库 libsmath.a。

2.5 编译成可执行文件

大部分编译规则与动静态库的书写方法一样,主要是加上下面语句:

include $(BUILD_EXECUTABLE)

3、常用NDK命令行参数:

参考:http://blog.51cto.com/ticktick/1425857

Android提供了NDK工具,用来编译native代码(c/c++),该工具配置好了相关的交叉编译环境和工具链,只需要你简单地编写几个.mk文件即可将你的c/c++代码编译为Android的java工程/Android手机可以识别、加载和运行的库或者应用程序。

默认情况下,使用NDK编译c/c++代码,需要将该代码放置到任一个Android应用工程的jni目录下,然后编写相应的Android.mk文件,并执行ndk-build命令完成编译。其实你也是可以在任意目录下去编译native代码的,只需要在ndk-build命令后面添加相应的命令行参数即可,这里给出一些常用的ndk-build命令行参数,方便大家灵活地使用NDK编译自己的native代码。


1. ndk-build NDK_LOG=1
用于配置LOG级别,打印ndk编译时的详细输出信息

2. ndk-build NDK_PROJECT_PATH=.
指定NDK编译的代码路径为当前目录,如果不配置,则必须把工程代码放到Android工程的jni目录下

3. ndk-build APP_BUILD_SCRIPT=./Android.mk
指定NDK编译使用的Android.mk文件

4. ndk-build NDK_APP_APPLICATION_MK=./Application.mk
指定NDK编译使用的application.mk文件

5. ndk-build clean
清除所有编译出来的临时文件和目标文件

6. ndk-build -B
强制重新编译已经编译完成的代码

7. ndk-build NDK_DEBUG=1
执行 debug build

8. ndk-build NDK_DEBUG=0
执行 release build

9. ndk-build NDK_OUT=./mydir
指定编译生成的文件的存放位置

10. ndk-build -C /opt/myTest/
到指定目录编译native代码   

4、ndk工程目录编译后libs与obj目录下库文件的区别

参考:https://blog.csdn.net/bidgod/article/details/6930440
在执行NDK编译之后,编译器会生成libs和obj两个目录,并且libs/armeabi中和obj/local/armeabi中都包含可执行文件和动态库,区别何在呢?

As part of the build process, the files in the libs folder have been stripped of symbols and debugging information. So you’ll want to keep two copies of each of your .so files: One from the libs folder to install on the Android device, and one from the obj folder to install for GDB to get symbols from.
libs目录下生成的库是剥离了符号表与调试信息的,而obj下的库是带有调试信息的。

5、Android.mk和Application.mk说明

关于Application.mk , Android.mk和JNI的介绍可参考:
https://developer.android.google.cn/ndk/guides/android_mk
https://developer.android.google.cn/ndk/guides/application_mk
通用模块编译可以采用Android_lib.mk,Android_app.mk和common.mk以及Application.mk采用ndk-build进行编译。
libmpeg2解码器的Android平台编译:
libmpeg2解码器的Android平台编译
示例:
common.mk:设置源文件目录以及头文件目录:配置LOCAL_C_INCLUDES和LOCAL_SRC_FILES.
Android_lib.mk:设置编译参数、特定平台编译参数、编译动静态库配置:配置LOCAL_PATH,LOCAL_MODULE,LOCAL_CFLAGS,LOCAL_CPPFLAGS。
Application.mk:设置APP_ABI,APP_PLATFORM和NDK_TOOLCHAIN_VERSION等。
补充说明及注意事项:
汇编(.asm,.S,.s)文件的编译参数设置:LOCAL_ASMFLAGS
C文件编译参数设置:LOCAL_CFLAGS
C++文件编译参数设置:LOCAL_CPPFLAGS
链接器参数设置:LOCAL_LDFLAGS

6、ndk-build的编译选项

https://developer.android.google.cn/ndk/guides/ndk-build

所有给ndk-build的选项都会直接传给GNU Make,由make运行NDK的编译脚本。几个常见调用方式如下:

 ndk-build clean 清掉二进制文件
  ndk-build NDK_DEBUG=1     编译为可调试版的二进制文件
  ndk-build NDK_DEBUG=0     编译为release版
  ndk-build V=1             执行ndk-build且打印出它所执行的详细编译命令。
  ndk-build -B              强制重新编译
  ndk-build -B V=1          -B 和 V=1 的组合
  ndk-build NDK_LOG=1        打印出内部的NDK日志信息(用于调试NDK自己)
  ndk-build NDK_APPLICATION_MK=<文件路径>      用这里指定的路径寻找Application.mk文件
  ndk-build -C <project路径>  先cd进入<project路径>,然后执行ndk-build。

jni中如何指定编译器:
在jni/Application.mk中添加

NDK_TOOLCHAIN_VERSION :=4.9

NDK_TOOLCHAIN_VERSION. Define this variable as 4.9 to select that version of the GCC compiler. Define this variable as clang to select the Clang compiler,

7、编译脚本

Android平台通用编译环境

8、编译模板

Android平台通用编译模板

更多参考网址:
https://www.cnblogs.com/wanghuaijun/p/8092747.html
https://blog.csdn.net/listener51/article/details/84026778
https://www.tuicool.com/articles/QZJ3qa
https://blog.csdn.net/crash163/article/details/52228412

9、Android平台编译注意事项

  1. 当前最新版本的android-ndk版本是r16b。将x86纯汇编代码编译为x86_64平台Android程序时,报出如下问题:
    Android.mk: Unsupported source file extensions for "xxxxxxxxxx"

原因: 采用ndk版本为r10。该版本不支持x86_64平台上的asm汇编文件的编译,不识别asm格式的文件。这样会导致编译时忽略掉asm文件的编译。
解决方案: 经过测试,r10,r10b都不支持x86_64平台上的asm汇编编译,r10e和更高版本的ndk支持x86_64平台上的asm汇编编译。


THE END!


本博文只能阅读,谢绝转载,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 2963033731@qq.com

文章标题:Android平台编译makefile编写规则

字数:2k

本文作者:Soaring Lee

发布时间:2018-11-13, 15:13:47

最后更新:2021-06-14, 12:13:44

原始链接:https://soaringleefighting.github.io/2018/11/13/【android】Android平台编译makefile编写规则/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

×

喜欢就点赞,疼爱就打赏

相册