1

我想查看 Gradle 项目的属性,以手动确保值看起来正确。

properties当我从多项目构建的根目录调用任务时,它会列出根项目的属性:

$ gradle -q properties

------------------------------------------------------------
Root project
------------------------------------------------------------

allprojects: [root project 'myapp', project ':api', project ':model', project ':ui']
ant: org.gradle.api.internal.project.DefaultAntBuilder@12345
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory@12345
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated@12345
asDynamicObject: DynamicObject for root project 'myapp'
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope@12345
[...]

我还可以为每个单独的子项目请求属性:

$ gradle -q :api:properties

------------------------------------------------------------
Project :api - The shared API for the application
------------------------------------------------------------

allprojects: [project ':api']
ant: org.gradle.api.internal.project.DefaultAntBuilder@12345
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory@12345
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated@12345
asDynamicObject: DynamicObject for project ':api'
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope@12345
[...]

但是,我真正想做的是一次列出给定项目及其所有子项目的属性。

我有点惊讶在根级别调用任务只提供根级别属性。这似乎与 Gradle 文档中关于在多项目构建中按名称执行任务相矛盾:

该命令gradle test将在具有该test任务的任何子项目中执行该任务,相对于当前工作目录。如果从项目根目录运行命令,您将testapisharedservices:sharedservices:webservice中运行。如果您从 services 项目目录运行命令,您将只执行 services:shared 和 services:webservice 中的任务。

Gradle 行为背后的基本规则是:执行层次结构中具有此名称的所有任务。只有在遍历的任何子项目中都没有找到这样的任务时才抱怨。

如何一次列出项目及其子项目的所有属性?作为奖励,为什么不在properties根级别运行的任务也为子项目运行?我正在使用当前最新版本的 Gradle (6.7.1)。

4

2 回答 2

1

根据此 Gradle 论坛响应,子项目的属性任务未运行,因为impliesSubProjects属性任务的属性true在属性实现中:

该任务被配置为通过HelpTasksPlugin使用内部 API忽略子项目任务

[…]

如果是,TaskNameResolver则不查看任务的子项目。impliesSubProjectstrue

实验表明,impliesSubProjects可以在构建文件中配置该属性,从而允许为父项目及其所有子项目运行任务:

properties {
    impliesSubProjects = false
}

输出

$ gradle -q properties

------------------------------------------------------------
Root project
------------------------------------------------------------

allprojects: [root project 'myapp', project ':api', project ':model', project ':ui']
ant: org.gradle.api.internal.project.DefaultAntBuilder@12345
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory@12345
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated@12345
asDynamicObject: DynamicObject for root project 'myapp'
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope@12345
[...]

------------------------------------------------------------
Project :api - The shared API for the application
------------------------------------------------------------

allprojects: [project ':api']
ant: org.gradle.api.internal.project.DefaultAntBuilder@12345
antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory@12345
artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated@12345
asDynamicObject: DynamicObject for project ':api'
baseClassLoaderScope: org.gradle.api.internal.initialization.DefaultClassLoaderScope@12345
[...]

------------------------------------------------------------
Project :model - Shared object model
------------------------------------------------------------
[...]

但是请注意,该impliesSubProjects属性是在内部 API 中定义的(org.gradle.api.internal.AbstractTask并且不是公共TaskAPI 的一部分(有关内部 API 的更多详细信息,请参阅避免使用内部 Gradle API)。因此,如链接论坛响应中所述,这不是旨在用于构建:

请记住,这是一个内部实现细节,不打算由构建使用,并且不能保证它会在未来的 Gradle 版本中继续工作。

但是,在不是构建的持久部分的一次性属性比较的情况下,这种意外使用可能是可以接受的。

于 2020-12-23T16:36:47.700 回答
0

可能是我错误地理解了你的问题。如果要列出所有属性,包括所有子项目以及根项目,则可以按如下方式创建构建文件:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

allprojects {
    repositories {
        mavenCentral()
    }

    group = "com.nononsensecode"
    version = "0.0.1"

}

plugins {
    kotlin("jvm") version "1.4.20" apply false
    base
}

configure(subprojects) {
    apply {
        plugin("org.jetbrains.kotlin.jvm")
    }

    configure<JavaPluginExtension> {
        sourceCompatibility = org.gradle.api.JavaVersion.VERSION_1_8
        targetCompatibility = org.gradle.api.JavaVersion.VERSION_1_8
    }

    tasks.withType<KotlinCompile>().configureEach {
        kotlinOptions {
            jvmTarget = "1.8"
            freeCompilerArgs = listOf("-Xjsr305=strict")
        }
    }

    dependencies {
        val implementation by configurations

        implementation(kotlin("stdlib-jdk8"))
        implementation(kotlin("reflect"))
    }

    task("listAllProperties") {
        val subProjectPropertiesMap = mutableMapOf<String, Map.Entry<String, Any?>>()
        subprojects.forEach { subProject ->
            subProject.properties.forEach { property ->
                subProjectPropertiesMap[subProject.name] = property
            }
        }

        val allProperties = AllProperties(properties, subProjectPropertiesMap)
        println(allProperties)
    }
}

data class AllProperties(
    val properties: Map<String, Any?>,
    val subProjectProperties: MutableMap<String, Map.Entry<String, Any?>>
)

然后运行任务gradlew listAllProperties。如果你愿意,你可以创建一个toString方法来以漂亮的方式打印所有属性。

于 2020-12-12T03:14:51.813 回答