Android Gradle多项目依赖关系解析

时间:2018-07-02 04:45:33

标签: android xamarin gradle xamarin.android android-gradle

在我的Android项目中,我有一个将构建依赖项复制到外部目录的任务,如下所示:

task copyBuildDependencies(type: Copy) {
    delete "$buildDir/dependencies"
    afterEvaluate {
        from configurations.releaseCompileClasspath
        into "$buildDir/dependencies"

        doLast {
            FileTree files = fileTree("$buildDir/dependencies")
            files.forEach { file ->
                if (file.isFile() && file.name.endsWith(".aar")) {
                    copy {
                        from zipTree(file).matching { include "*.jar" }
                        into "$buildDir/dependencies"
                        eachFile {
                            it.path = it.path.replace(it.name, "${file.name}-${it.name}")
                        }
                    }
                }
            }
        }
    }
}

我具有正常的项目依赖项:

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    ...
    implementation 'com.google.guava:guava:11.0.2'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.5'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5'
    // Note: These are Android Library projects
    implementation project(':genericutils')
    implementation project(':module2')
    ...
}

运行任务copyBuildDependencies时出现以下错误:

Executing task 'copyBuildDependencies'...

Executing tasks: [copyBuildDependencies]

Configuration on demand is an incubating feature.

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':BiometricInterfaceLib:copyBuildDependencies'.
> Could not resolve all task dependencies for configuration ':BiometricInterfaceLib:releaseCompileClasspath'.
> More than one variant of project :genericutils matches the consumer attributes:
    - Configuration ':genericutils:releaseApiElements' variant android-aidl:
        - Found artifactType 'android-aidl' but wasn't required.
        - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
        - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
        - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
        - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
    - Configuration ':genericutils:releaseApiElements' variant android-classes:
        - Found artifactType 'android-classes' but wasn't required.
        - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
        - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
        - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
        - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
    - Configuration ':genericutils:releaseApiElements' variant android-manifest:
        - Found artifactType 'android-manifest' but wasn't required.
        - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
        - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
        - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
        - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
    - Configuration ':genericutils:releaseApiElements' variant android-renderscript:
        - Found artifactType 'android-renderscript' but wasn't required.
        - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
        - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
        - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
        - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
    - Configuration ':genericutils:releaseApiElements' variant jar:
        - Found artifactType 'jar' but wasn't required.
        - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
        - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
        - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
        - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
> More than one variant of project :module2 matches the consumer attributes:
    - Configuration ':module2:releaseApiElements' variant android-aidl:
        - Found artifactType 'android-aidl' but wasn't required.
        - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
        - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
        - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
        - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
    - Configuration ':module2:releaseApiElements' variant android-classes:
        - Found artifactType 'android-classes' but wasn't required.
        - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
        - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
        - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
        - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
    - Configuration ':module2:releaseApiElements' variant android-manifest:
        - Found artifactType 'android-manifest' but wasn't required.
        - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
        - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
        - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
        - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
    - Configuration ':module2:releaseApiElements' variant android-renderscript:
        - Found artifactType 'android-renderscript' but wasn't required.
        - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
        - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
        - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
        - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
    - Configuration ':module2:releaseApiElements' variant jar:
        - Found artifactType 'jar' but wasn't required.
        - Required com.android.build.api.attributes.BuildTypeAttr 'release' and found compatible value 'release'.
        - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
        - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
        - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 2s
16:39:07: Task execution finished 'copyBuildDependencies'.

我可以在configurations.releaseCompileClasspath上使用“排除模块”选项,但是assembleRelease任务失败,因为它找不到依赖项。

编辑:我创建了一个示例项目,以帮助显示我所追求的结果和遇到的问题:https://forums.developer.apple.com/thread/68477

---编辑2 ---

需要库模块而不是库的Jar的原因是为了可以创建Xamarin绑定库。

因此,Xamarin绑定所需的是库的AAR(在示例代码的情况下为master模块)和所有依赖库的Jar。 例如:

mastermodule/build/dependencies/
├── animated-vector-drawable-28.0.0-alpha3.aar-classes.jar
├── annotations-13.0.jar
...
├── collections-28.0.0-alpha3.jar
├── common-1.1.1.jar
├── coordinatorlayout-28.0.0-alpha3.aar-classes.jar
...
etc

1 个答案:

答案 0 :(得分:1)

如果我理解正确

  1. 您的项目是一个Android库项目。
  2. 您的复制任务尝试复制AAR库中的所有jar。
  3. 重命名classes.jar。

下面可能是您想要的。将其添加到 root 项目下的build.gradle中。

// Add this into the build.gradle under **root** project.
// Add the modules that you want to exclude from having this copyXXXJar task.
def modulesExcluded = [
        'app',
        'mastermodulewantedoutput'
]

subprojects { prj ->

    // Skip excluded modules
    if (modulesExcluded.contains(prj.name)) {
        prj.afterEvaluate {
            tasks['preBuild'].dependsOn(copyModuleJars)
        }
        return
    }

    prj.afterEvaluate {

        /**
         * Dynamically create task "copyXXXJar" according to build variant of each library module.
         */
        android.libraryVariants.all { variant ->

            def capitalizedVariantName = variant.name.capitalize()
            def variantName = variant.flavorName
            if (!variantName || variantName == "") {
                variantName = variant.buildType.name
            } else {
                variantName += "-${variant.buildType.name}"
            }
            //================================================================================
            // Define build/copy variant jar and copy to dependencies
            //================================================================================
            def copyJarTask = project.tasks.create("copy${capitalizedVariantName}Jar", Copy) {
                group "Copy Jar"
                description "Rename the classes.jar to ${project.name}-${variantName}.jar and copy it into dist folder."


                def fromDirModule = "$buildDir/outputs/aar/${project.name}-${variantName}.aar"
                def intoDirModule = "$rootDir/dependencies/$variant.buildType.name"
                from(zipTree(fromDirModule))
                into(intoDirModule)
                include('*.jar')
                include('libs/*.jar')
                rename('classes.jar', "${project.name}-${variantName}.jar")

                dependsOn "assemble${capitalizedVariantName}"
            }
            copyModuleJars.dependsOn(copyJarTask)
        }
    }
}

// Task to copy all the modules' jars. It can be run with command [ ./gradlew copyModuleJars ]
task copyModuleJars {
    group = 'Copy Jar'
    description = 'Copy the classes.jar from each module.'
} 

运行以下命令进行验证

./gradlew copyModuleJars

希望有帮助。

--------- 已编辑 ----------

我检查了您的gitlab项目。看起来您只需要.aar内部的jar。我想说这可能会引起一些问题,因为您删除了关联的res文件,aidl文件,资产和R.txt等,它们被视为.aar库的必要部分。例如,您的一个依赖项 appcompat-v7-28.0.0-alpha3 在您解压缩时实际上将具有以下布局,不仅限于classes.jar appcompat-v7-28.0.0-alpha3 contents

此外,您可以像我在上面编辑的那样简单地修改 modulesExcluded 数组。并且可以删除条件检查“ hasProperty()”。

输出将在“ $ rootDir / dependencies ”下。如下所示:

  • 调试
    • genericutils-debug.jar
    • mastermodule-debug.jar
  • 发布
    • genericutils-release.jar
    • mastermodule-release.jar

这些jar是从您自己的源代码生成的,即您的 genericutils mastermodule 源。如果库的传递依赖项为“ .jar ”格式,则它们将进入 .aar 的“ libs / ”格式为“ .aar ”,我认为您不能简单地选择其 classes.jar ,而是剥离其相关的必要部分,除非您有一些特殊要求,缺少部分与您的项目无关。

-------- 已编辑2 ---------

如果您只关心源代码,而在代码逻辑中不使用任何资源(res,R.txt,aidl,jni等),例如可能您的 genericutils 模块就是这种情况,那么您只需简单地选择classes.jar。当您将其用作普通Java库时,它不会引起任何问题。