You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

首次运行Gradle构建找不到依赖:Android项目依赖配置问题

Android NDK模块构建顺序问题解决

问题背景

项目结构如下:

App
  settings.gradle
  library
    library
    library1
    library2

library模块依赖library1和library2,当前配置:

  1. settings.gradle:
....
include ':library-library1'
include ':library-library2'
include ':library-library'
....
  1. library模块build.gradle:
android{
....
}

dependencies {
    implementation project(':library-library1')
    implementation project(':library-library2')
}
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:46:03