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

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

1. 準備環境
首先,你得安裝了Android的NDK編譯工具,假設你的NDK的根目錄在 /opt/android/ndk .c++

固然,最好你能在環境變量裏配置一下路徑,不然使用ndk-build命令的時候,都得加上路徑的前綴了。bash

修改 ~/.bashrc函數

export NDK_HOME=/opt/android/ndk
export PATH=$NDK_HOME:$PATH
NDK_HOME=/opt/android/ndk
export PATH=$NDK_HOME:$PATH
1
2
3
4
而後執行:工具

$ source ~/.bashrc
/.bashrc
1
2
2. 編寫 .c 文件
假設你在 ~/math 目錄下編寫了一個 math.c 文件,內容以下:ui

#include <stdio.h>this

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


int add( int a , int b ) {
    return a+b;
}
1
2
3
4
5
6
7
8
9
10
OK,後面咱們就準備在 ~/math 目錄下,將這個.c文件編譯爲Android可以使用的靜態庫/動態庫了。debug

3. 編譯成動態庫
編寫 Android.mk 文件,內容以下:調試

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
根據前一篇文章,咱們能夠知道,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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
一樣,在 ~/math 目錄下執行:

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

關於在任意目錄將c/c++代碼編譯爲Android可以使用的靜態庫/動態庫就介紹到這裏了,瞭解了這個編譯過程,對你未來用ndk編譯第三方庫會頗有幫助,另外,若是但願編譯爲C/C++應用程序在Android機器上運行的話,只須要在代碼中加一個main函數,修改Android.mk中的最後一行爲 include $(BUILD_EXECUTABLE) 便可。有任何疑問歡迎留言或者來信lujun.hust@gmail.com交流。

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。
1
2
3
4
5
6
7
8
9
10
6. 編譯過程,怎麼查看腳本中(makefile)中的變量
$(warning $(XXXX))
1
7. jni中如何指定編譯器
在jni/Application.mk中添加

NDK_TOOLCHAIN_VERSION :=4.9
1
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. 待續 參考網址:http://www.tuicool.com/articles/QZJ3qa

相關文章
相關標籤/搜索