前言
安卓NDK編譯會涉及到:源碼編譯、製作靜態鏈接庫/靜態庫依賴編譯、製作動態鏈接庫/動態鏈接庫依賴編譯、嵌套編譯,這幾個組合類別。
本文將對這些編譯搭配類別進行編譯演示以快速入門掌握編譯方法。Android.mk、Application.mk等全面語法請查閱其他文章。
https://blog.csdn.net/a04081122/article/details/52279799
0x01 NDK工程目錄和純源碼可執行文件編譯
純源碼:材料僅有源碼.c/.cpp源文件和.h頭文件。
test
└─jni
│ Android.mk
│ Application.mk
│ test.c
│
└─include
func.h
ndk-build會到jni子目錄中尋找Androkd.mk和Application.mk等配置文件,所以源碼、頭文件之類的爲了簡便,也以jni目錄爲相對目錄放置。
# Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := test.c
LOCAL_CONLYFLAGS := -std=c11
include $(BUILD_EXECUTABLE)
#如你的理解,指定了c11標準進行編譯,編譯後的模塊名爲test,直接編譯文件爲test.c。
# Application.mk
APP_ABI := armeabi armeabi-v7a arm64-v8a x86 x86_64
APP_PLATFORM := android-14
# 如你的理解,需要編譯 ... 等平臺,最低兼容android-14平臺
E:\Workspace\NDK\test> ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-14.
[arm64-v8a] Compile : test <= test.c
[arm64-v8a] Executable : test
[arm64-v8a] Install : test => libs/arm64-v8a/test
[armeabi-v7a] Compile thumb : test <= test.c
[armeabi-v7a] Executable : test
[armeabi-v7a] Install : test => libs/armeabi-v7a/test
[x86] Compile : test <= test.c
[x86] Executable : test
[x86] Install : test => libs/x86/test
[x86_64] Compile : test <= test.c
[x86_64] Executable : test
[x86_64] Install : test => libs/x86_64/test
看來沒啥問題,讓我們看看編譯後的目錄結構。
test
├─jni
│ │ Android.mk
│ │ Application.mk
│ │ test.c
│ │
│ └─include
│ func.h
│
├─libs
│ ├─arm64-v8a
│ │ test
│ │
│ ├─armeabi-v7a
│ │ test
│ │
│ ├─x86
│ │ test
│ │
│ └─x86_64
│ test
│
└─obj
└─...
將libs目錄中對應架構文件推送到手機上即可運行。
0x02 動態鏈接庫編譯與依賴動態鏈接庫編譯
即當前最火熱的so文件。
# Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := adloog
LOCAL_SRC_FILES := adloog.cpp
LOCAL_CFLAGS := -Wall -Wextra -Werror -g
LOCAL_CONLYFLAGS := -std=c++11
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
與0x01編譯的可執行文件沒有太大區別,執行ndk-build便得到各架構的adloog.so文件。
現在有了新的組合方式,假設0x01的可執行文件依賴於這個動態鏈接庫,如何編譯?
# Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := adloog
LOCAL_SRC_FILES := $(LOCAL_PATH)/../libs/$(TARGET_ARCH_ABI)/adloog.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := test.c
LOCAL_SHARED_LIBRARIES := adloog
LOCAL_CFLAGS := -Wall -Wextra -Werror -g
LOCAL_CONLYFLAGS := -std=c11
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
使用include $(PREBUILT_SHARED_LIBRARY)對依賴庫進行預處理,隨後在編譯的主模塊(即test)上使用LOCAL_SHARED_LIBRARIES選項指定需要鏈接的動態鏈接庫標識。
0x03 靜態鏈接庫編譯與依賴靜態鏈接庫編譯
靜態編譯將會輸出.a文件,用於後續的靜態鏈接。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := adloop
LOCAL_SRC_FILES := adloop1.c adloop2.c
include $(BUILD_STATIC_LIBRARY)
嗯,都是重複的,於是越寫越少了。
現在有了新的組合方式,假設0x01的可執行文件依賴於這個靜態鏈接庫,如何編譯?
LOCAL_PATH := $(call my-dir)
NDK_MODULE_PATH = E:\Workspace\NDK
include $(CLEAR_VARS)
LOCAL_MODULE := adloop
LOCAL_SRC_FILES := $(LOCAL_PATH)/../libs/$(TARGET_ARCH_ABI)/adloop.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := test.c
LOCAL_STATIC_LIBRARIES := adloop
LOCAL_CFLAGS := -Wall -Wextra -Werror -g
LOCAL_CONLYFLAGS := -std=c11
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
0x04 那麼問題來了,現在我需要將0x01作爲主模塊,同時依賴於0x02的動態鏈接庫和0x03的靜態鏈接庫,該怎麼編譯?
Well,這個問題留給聰明的你。
0x05 嵌套編譯
別人寫好了一個NDK庫,具體需要的編譯選項他寫在自己的Android.mk。如何在我的Android.mk中包含這個庫呢?
# 自己的Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := adloog
LOCAL_SRC_FILES := adloog.cpp
LOCAL_STATIC_LIBRARIES := adloop
LOCAL_CFLAGS := -Wall -Wextra -Werror -g
LOCAL_CONLYFLAGS := -std=c++11
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
$(call import-add-path, $(LOCAL_PATH)\..\..\adloop
$(call import-module, libhook)
值得一說的是call系列調用要放在Android.mk最後。
# 別人的Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := adloop
LOCAL_SRC_FILES := static/$(TARGET_ARCH_ABI)/adloop.a
include $(PREBUILT_STATIC_LIBRARY)
$(call import-module)用於搜尋第三庫的Android.mk編譯規則。
這裏要注意,如果不存在這個規則NDK不會給明顯的錯誤,而是下面的形式:
ndk-build
D:/RTEws/Android/android-ndk-r16b/build//../build/core/setup-app.mk:81: Android NDK: Application targets deprecated ABI(s): armeabi
D:/RTEws/Android/android-ndk-r16b/build//../build/core/setup-app.mk:82: Android NDK: Support for these ABIs will be removed in a future NDK release.
Android NDK: E:/Workspace/NDK/test/jni/Android.mk: Cannot find module with tag 'adloop' in import path
Android NDK: Are you sure your NDK_MODULE_PATH variable is properly defined ?
Android NDK: The following directories were searched:
Android NDK:
E:/Workspace/NDK/test/jni/Android.mk:20: *** Android NDK: Aborting. . Stop.
嗯。。無提示錯誤,最爲致命。那麼怎麼修改?用0x02或0x03不就完事了。
0x06 那麼問題...別鬧了你都會了
完。