NDK 編譯可執行程序( 獨立編譯)(一)

什么是NDK?

定義:Native Development Kit,是Android的一種開發工具包(其實就是在安卓平臺編寫C和C++程序的開發包

作用:最主要的就是開發so庫了,c或c++代碼編譯成動態鏈接庫供java代碼調用

優點:

運行效率高
代碼安全性高
跨平臺

使用場景

對性能要求比較高或者對安全要求比較高的Android程序可以使用NDK

ndk下載鏈接https://developer.android.google.cn/ndk/downloads/
使用之后請自行配置環境變量

編寫可執行程序

  • 創建一個目錄(這里我創建目錄為jni)
    image.png

    目錄中有三個文件Android.mk,Application.mk,hello-jni.c
    下面我們分別介紹一下這三個文件
  • hello-jni.c
#include <stdio.h>
 int main()
{
    printf("Hello Android!\n");
    return 0;
}

hello-jni.c是源碼文件,編寫c或者c++代碼

  • Application.mk
#### 0APP_ABI := arm64-v8a 后面接的是需要生成的.so平臺文件,
#### 正常手機使用arm64處理器的即可。 all是全平臺
#### APP_PLATFORM :=后面接的是使用SDK的最低等級
APP_ABI := all

Application.mk為指定平臺文件

  • Android.mk
# 一個Android.mk file首先必須定義好LOCAL_PATH變量。
# 它用于在開發樹中查找源文件。在這個例子中,宏函數’my-dir’, 
# 由編譯系統提供,用于返回當前路徑(即包含Android.mk file文件的目錄)。
LOCAL_PATH := $(call my-dir)
# CLEAR_VARS由編譯系統提供,
# 指定讓GNU MAKEFILE為你清除許多LOCAL_XXX變量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH 。這是必要的,
# 因為所有的編譯控制文件都在同一個GNU MAKE執行環境中,所有的變量都是全局的。
include $(CLEAR_VARS)
# LOCAL_MODULE變量必須定義,以標識你在Android.mk文件中描述的每個模塊。名稱必須是唯一的,而且不包含任何空格。
# 注意編譯系統會自動產生合適的前綴和后綴,換句話說,一個被命名為'foo'的共享庫模塊,將會生成'libfoo.so'文件。
LOCAL_MODULE    := hello-jni
# LOCAL_SRC_FILES變量必須包含將要編譯打包進模塊中的C或C++源代碼文件。注意,你不用在這里列出頭文件和包含文件,
# 因為編譯系統將會自動為你找出依賴型的文件;僅僅列出直接傳遞給編譯器的源代碼文件就好。
LOCAL_SRC_FILES := hello-jni.c
# BUILD_EXECUTABLE 表示以一個可執行程序的方式進行編譯
# BUILD_SHARED_LIBRARY 表示動態鏈接庫的方式進行編譯
include $(BUILD_EXECUTABLE)

Android.mk指定編譯的一些參數(注釋比較詳細)

使用ndk-build

  • 進入到創建的jni目錄使用ndk-build編譯


    image.png
  • 在jni同級目錄下會出現libs文件夾,進入該文件夾如下:
    image.png

    可以看到所有的平臺,這里我們使用armeabi-v7a的,因為我們的虛擬機是armeabi-v7a
    注意:這里一定要創建arm架構的虛擬機,因為我們的Android手機基本都是arm架構的
    image.png
  • 進入armeabi-v7a文件夾可以看到有編譯好的可執行程序:


    image.png
  • 下面就是將這個可執行程序push到手機上,然后運行它了(先啟動安卓虛擬機)
#進入手機shell
adb shell
#創建文件夾
mkdir /data/tmp/
#退出shell
exit
#push可執行程序進入手機(這里路徑根據自己的修改)
adb push C:\Users\15079\Desktop\libs\armeabi-v7a\hello-jni /data/tmp
#再次進入手機shell
adb shell
#進入到可執行程序的文件夾
cd /data/tmp
#給權限
chmod 777 hello-jni
#運行
./hello-jni

最后結果如下:


image.png

尾言

這里我們編寫一個簡單的NDK可執行程序作為例子,真正的情況一般是編譯為so庫,我將在下一章使用eclipse+NDK編寫一個簡單的so庫,并使用JNI技術在java中調用這個so庫,這也是我們項目中一般使用到的場景。
在IDA反匯編中so庫的源碼將變成ARM匯編代碼,而不是Intel X86的匯編,所以我們有必要學習一下ARM匯編

ARM手冊(需翻墻)
https://docs.google.com/viewer?url=http%3A%2F%2Fwww.scss.tcd.ie%2F%7Ewaldroj%2F3d1%2Farm_arm.pdf

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。