如何在基于Android.mk的Android项目中引入CMake项目?
如何在Android.mk构建的项目中引入仅提供CMakeLists.txt的依赖(funchook & capstone)
问题描述
我正在构建Android原生项目,当前采用Android.mk进行构建。现需引入两个依赖项目:funchook(依赖capstone),但这两个项目仅提供CMakeLists.txt而非Android.mk,请问是否有方法引入这些CMake项目?
当前项目目录结构:
├── build.gradle ├── jni │ ├── Android.mk │ ├── Application.mk │ ├── example.cpp │ └── libcxx └── src └── main └── AndroidManifest.xml
Android.mk 配置:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := example LOCAL_SRC_FILES := example.cpp LOCAL_STATIC_LIBRARIES := libcxx LOCAL_LDLIBS := -llog include $(BUILD_EXECUTABLE) include jni/libcxx/Android.mk
Application.mk 配置:
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64 APP_CPPFLAGS := -std=c++17 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden APP_STL := none APP_PLATFORM := android-21
AndroidManifest.xml 配置:
<?xml version="1.0" encoding="utf-8"?> <manifest package="native" />
解决方案
方法1:通过ndk-build直接调用CMake构建依赖
ndk-build(r21及以上版本)支持在Android.mk中调用CMake编译外部项目,生成静态库后直接链接到主项目:
将funchook和capstone源码放到项目
jni/thirdparty目录下,结构如下:jni/ └── thirdparty/ ├── capstone/ └── funchook/修改主Android.mk,添加依赖编译逻辑:
LOCAL_PATH := $(call my-dir) # 编译capstone静态库 include $(CLEAR_VARS) LOCAL_MODULE := capstone LOCAL_SRC_FILES := thirdparty/capstone/CMakeLists.txt # 传递CMake编译参数,关闭动态库、测试编译 LOCAL_CMAKE_FLAGS := -DCAPSTONE_BUILD_SHARED=OFF -DCAPSTONE_BUILD_STATIC=ON -DCAPSTONE_BUILD_TESTS=OFF include $(BUILD_CMAKE_PROJECT) # 编译funchook静态库(依赖capstone) include $(CLEAR_VARS) LOCAL_MODULE := funchook LOCAL_SRC_FILES := thirdparty/funchook/CMakeLists.txt LOCAL_CMAKE_FLAGS := -DFUNCHOOK_BUILD_SHARED=OFF -DFUNCHOOK_BUILD_STATIC=ON -DFUNCHOOK_USE_CAPSTONE=ON LOCAL_STATIC_LIBRARIES := capstone include $(BUILD_CMAKE_PROJECT) # 更新主可执行文件的依赖 include $(CLEAR_VARS) LOCAL_MODULE := example LOCAL_SRC_FILES := example.cpp LOCAL_STATIC_LIBRARIES := libcxx capstone funchook LOCAL_LDLIBS := -llog include $(BUILD_EXECUTABLE) include jni/libcxx/Android.mk
方法2:预编译依赖为静态库后引入
提前用CMake编译好对应ABI的静态库,再复制到项目中通过Android.mk引用:
用CMake或Android Studio针对每个目标ABI(armeabi-v7a、arm64-v8a等)编译capstone和funchook的静态库(
.a文件)。在项目
jni目录下创建libs/[ABI]结构,将对应ABI的静态库放入:jni/ └── libs/ ├── armeabi-v7a/ │ ├── libcapstone.a │ └── libfunchook.a ├── arm64-v8a/ │ ├── libcapstone.a │ └── libfunchook.a ├── x86/ │ ├── libcapstone.a │ └── libfunchook.a └── x86_64/ ├── libcapstone.a └── libfunchook.a修改Android.mk引入预编译库:
LOCAL_PATH := $(call my-dir) # 引入预编译的capstone静态库 include $(CLEAR_VARS) LOCAL_MODULE := capstone LOCAL_SRC_FILES := libs/$(TARGET_ABI)/libcapstone.a include $(PREBUILT_STATIC_LIBRARY) # 引入预编译的funchook静态库 include $(CLEAR_VARS) LOCAL_MODULE := funchook LOCAL_SRC_FILES := libs/$(TARGET_ABI)/libfunchook.a LOCAL_STATIC_LIBRARIES := capstone include $(PREBUILT_STATIC_LIBRARY) # 更新主可执行文件依赖 include $(CLEAR_VARS) LOCAL_MODULE := example LOCAL_SRC_FILES := example.cpp LOCAL_STATIC_LIBRARIES := libcxx capstone funchook LOCAL_LDLIBS := -llog include $(BUILD_EXECUTABLE) include jni/libcxx/Android.mk
方法3:迁移整个项目到CMake构建
如果长期维护项目,建议直接切换到CMake构建,更便于依赖管理:
在
app/src/main/cpp目录下创建CMakeLists.txt,替换原Android.mk逻辑:cmake_minimum_required(VERSION 3.18.1) project(example) # 引入capstone和funchook子项目 add_subdirectory(../../jni/thirdparty/capstone capstone_build) add_subdirectory(../../jni/thirdparty/funchook funchook_build) # 构建主可执行文件 add_executable(example ../../jni/example.cpp ) # 链接依赖库 target_link_libraries(example log libcxx capstone funchook ) # 设置编译参数 target_compile_options(example PRIVATE -std=c++17 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden ) set_target_properties(example PROPERTIES CXX_STANDARD 17 )修改
build.gradle配置CMake构建:android { defaultConfig { externalNativeBuild { cmake { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' arguments "-DANDROID_PLATFORM=android-21", "-DANDROID_STL=none" } } } externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" } } }
内容的提问来源于stack exchange,提问作者Alexandru Nitan
相关产品推荐
相关产品推荐

