1. 程式人生 > >【Android開發】:在任意目錄執行NDK編譯

【Android開發】:在任意目錄執行NDK編譯

本文以簡單的例子講述如何在任意目錄把自己寫的C程式碼使用NDK提供的交叉編譯該工具來編譯成Android可使用的靜態庫/動態庫。

1. 準備環境

首先,你得安裝了Android的NDK編譯工具,假設你的NDK的根目錄在 /opt/android/ndk .

當然,最好你能在環境變數裡配置一下路徑,否則使用ndk-build命令的時候,都得加上路徑的字首了。

修改 ~/.bashrc

export NDK_HOME=/opt/android/ndk export PATH=NDKHOME:NDK_HOME:PATH NDK_HOME=/opt/android/ndk export PATH=NDKH

OME:NDK_HOME:PATH 然後執行:

$ source ~/.bashrc /.bashrc

2. 編寫 .c 檔案

假設你在 ~/math 目錄下編寫了一個 math.c 檔案,內容如下:

#include <stdio.h>

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

int add( int a , int b ) { return a+b; } OK,後面我們就準備在 ~/math 目錄下,將這個.c檔案編譯為Android可使用的靜態庫/動態庫了。

3. 編譯成動態庫

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS) LOCAL_MODULE := dmath LOCAL_SRC_FILES := math.c include $(BUILD_SHARED_LIBRARY) := $(call my-dir)

include $(CLEAR_VARS) LOCAL_MODULE := dmath LOCAL_SRC_FILES := math.c include $(BUILD_SHARED_LIBRARY) 在 ~/math 目錄下,執行 ndk-build 命令,引數如下:

$ ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk 根據前一篇文章,我們可以知道,NDK_PROJECT_PATH 指定了需要編譯的程式碼的工程目錄,這裡給出的是當前目錄,APP_BUILD_SCRIPT給出的是Android makefile檔案的路徑,當然,如果你還有

Application.mk 檔案的話,則可以新增 NDK_APPLICATION_MK=./Application.mk

執行完ndk-build命令後,你會發現當前目錄下,生成了 obj 和 libs 資料夾,這樣,你的libdmath.so動態庫就已經制作完成了,在 libs/armeabi 目錄下。

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)

include $(CLEAR_VARS) LOCAL_MODULE := dmath LOCAL_STATIC_LIBRARIES := smath LOCAL_SRC_FILES := math.c include $(BUILD_SHARED_LIBRARY) := $(call my-dir)

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

include $(CLEAR_VARS) LOCAL_MODULE := dmath LOCAL_STATIC_LIBRARIES := smath LOCAL_SRC_FILES := math.c include $(BUILD_SHARED_LIBRARY) 同樣,在 ~/math 目錄下執行:

$ ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk 你會在生成的 libs/armeabi 目錄下看到動態庫libdmath.so,在 obj/local/armeabi 目錄下看到靜態庫 libsmath.a

關於在任意目錄將c/c++程式碼編譯為Android可使用的靜態庫/動態庫就介紹到這裡了,瞭解了這個編譯過程,對你將來用ndk編譯第三方庫會很有幫助,另外,如果希望編譯為C/C++應用程式在Android機器上執行的話,只需要在程式碼中加一個main函式,修改Android.mk中的最後一行為 include $(BUILD_EXECUTABLE) 即可。有任何疑問歡迎留言或者來信[email protected]交流。

5. ndk-build的編譯選項

所有給ndk-build的選項都會直接傳給GNU Make,由make執行NDK的編譯指令碼。幾個常見呼叫方式如下:

ndk-build 編譯 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。

6. 編譯過程,怎麼檢視指令碼中(makefile)中的變數

$(warning $(XXXX))

7. 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,

針對r14b 安卓編譯包出現的編譯錯誤:

warning: shared library text segment is not shareable requires dynamic R_X86_64_PC32 reloc against ‘ff_pw_8’ which may overflow at runtime; recompile with -fPIC

8. ndk工程目錄編譯後libs與obj目錄下庫檔案的區別

    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下的庫是帶有除錯資訊的。 參考網址:https://blog.csdn.net/bidgod/article/details/6930440

9. 待續