1. 程式人生 > >【android】Android平臺編譯makefile編寫規則

【android】Android平臺編譯makefile編寫規則

Date: 2018.10.9


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/

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


https://developer.android.google.cn/ndk/guides/stable_apis#purpose

Android NDK說明:
主要是包括編譯C/C++程式碼的編譯器,需要按照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等。

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


THE END!