首次运行Gradle构建找不到依赖:Android项目依赖配置问题
Android NDK模块构建顺序问题解决
问题背景
项目结构如下:
App settings.gradle library library library1 library2
library模块依赖library1和library2,当前配置:
- settings.gradle:
.... include ':library-library1' include ':library-library2' include ':library-library' ....
- library模块build.gradle:
android{ .... } dependencies { implementation project(':library-library1') implementation project(':library-library2') }
- library模块Android.mk:
.... LOCAL_MODULE := library LOCAL_SRC_FILES := library.cpp LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../library1/include \ $(LOCAL_PATH)/../../library2/include LOCAL_LDLIBS := \ -L$(LOCAL_PATH)/../../library1/build/intermediates/library_jni/$(BUILD_TYPE)/jni/$(TARGET_ARCH_ABI) \ -L$(LOCAL_PATH)/../../library2/build/intermediates/library_jni/$(BUILD_TYPE)/jni/$(TARGET_ARCH_ABI) \ -llog -landroid -llibrary1 -llibrary2 LOCAL_CPPFLAGS += -fexceptions include $(BUILD_SHARED_LIBRARY) ....
核心问题:首次构建失败,报错找不到library1和library2的.so文件:
"error: cannot find -llibrary1" "error: cannot find -llibrary2"
首次构建后生成对应.so文件,后续构建正常,本质是library模块先于依赖的library1、library2执行NDK编译,导致找不到产物。
解决方法
1. 用Gradle统一管理NDK依赖(推荐)
放弃Android.mk中硬编码路径的写法,让Gradle自动处理依赖顺序和产物路径,推荐改用CMake(Android官方推荐替代Android.mk):
修改library模块build.gradle
android { ... defaultConfig { ... externalNativeBuild { cmake { cppFlags "-fexceptions" arguments "-DANDROID_STL=c++_shared" } } } externalNativeBuild { cmake { path "CMakeLists.txt" // 指向你的CMake配置文件路径 } } } dependencies { implementation project(':library-library1') implementation project(':library-library2') // 确保library1、library2的build.gradle也配置了externalNativeBuild }
对应CMakeLists.txt示例
cmake_minimum_required(VERSION 3.22.1) project(library) add_library(library SHARED library.cpp) // 链接依赖库,Gradle会自动处理构建顺序 target_link_libraries(library log android library1 library2) // 添加头文件路径 target_include_directories(library PRIVATE ../library1/include ../library2/include)
如果坚持用Android.mk,在build.gradle中显式关联依赖模块的JNI产物:
android { ... externalNativeBuild { ndkBuild { path "Android.mk" } } } dependencies { implementation project(':library-library1') implementation project(':library-library2') // 显式依赖JNI产物,强制Gradle先构建依赖模块 implementation files("${project(':library-library1').buildDir}/intermediates/library_jni/${buildType}/jni/${android.defaultConfig.ndk.abiFilters[0]}/liblibrary1.so") implementation files("${project(':library-library2').buildDir}/intermediates/library_jni/${buildType}/jni/${android.defaultConfig.ndk.abiFilters[0]}/liblibrary2.so") }
2. 给Android.mk传递Gradle变量,替换硬编码路径
避免写固定相对路径,通过Gradle把依赖模块的路径传递给Android.mk,同时强制依赖模块优先构建:
修改library模块Android.mk
.... LOCAL_MODULE := library LOCAL_SRC_FILES := library.cpp // 使用Gradle传递的变量 LOCAL_C_INCLUDES := $(LIBRARY1_INCLUDE) $(LIBRARY2_INCLUDE) LOCAL_LDLIBS := \ -L$(LIBRARY1_SO_PATH) \ -L$(LIBRARY2_SO_PATH) \ -llog -landroid -llibrary1 -llibrary2 LOCAL_CPPFLAGS += -fexceptions include $(BUILD_SHARED_LIBRARY) ....
修改library模块build.gradle
android { ... externalNativeBuild { ndkBuild { // 传递依赖模块的路径变量 arguments "LIBRARY1_INCLUDE=${project(':library-library1').projectDir}/include", "LIBRARY1_SO_PATH=${project(':library-library1').buildDir}/intermediates/library_jni/${buildType}/jni/${targetArchAbi}", "LIBRARY2_INCLUDE=${project(':library-library2').projectDir}/include", "LIBRARY2_SO_PATH=${project(':library-library2').buildDir}/intermediates/library_jni/${buildType}/jni/${targetArchAbi}" } } } dependencies { implementation project(':library-library1') implementation project(':library-library2') // 强制Gradle先评估并构建依赖模块 project.evaluationDependsOn(':library-library1') project.evaluationDependsOn(':library-library2') }
3. 显式指定settings.gradle中的模块顺序
虽然Gradle会根据依赖自动排序,但显式声明模块路径和顺序可以辅助确认:
.... include ':library-library1' include ':library-library2' include ':library-library' // 显式指定每个模块的路径,确保依赖模块先被识别 project(':library-library1').projectDir = new File(settingsDir, 'library/library1') project(':library-library2').projectDir = new File(settingsDir, 'library/library2') project(':library-library').projectDir = new File(settingsDir, 'library/library') ....
内容的提问来源于stack exchange,提问作者livfan
相关产品推荐
相关产品推荐

