Android.mk超快速入門/集成第三方庫/依賴編譯思路

前言

安卓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 那麼問題...別鬧了你都會了

完。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章