我可以在多项目构建中一次调用所有项目的 Gradle 属性任务吗?
Can I call the Gradle properties task on all projects at once in a multi-project build?
我想查看 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
[...]
但是,我真正想做的是一次列出给定项目及其所有子项目的属性。
我有点惊讶在根级别调用任务只提供根级别属性。这似乎与有关 executing tasks by name in a multi-project build:
的 Gradle 文档相矛盾
The command gradle test
will execute the test
task in any subprojects, relative to the current working directory, that have that task. If you run the command from the root project directory, you’ll run test
in api, shared, services:shared and services:webservice. If you run the command from the services project directory, you’ll only execute the task in services:shared and services:webservice.
The basic rule behind Gradle’s behavior is: execute all tasks down the hierarchy which have this name. Only complain if there is no such task found in any of the subprojects traversed.
如何一次列出项目及其子项目的所有属性?作为奖励,为什么根级别的 properties
任务 运行 也不是子项目的 运行ning?我正在使用当前最新版本的 Gradle (6.7.1)。
可能是我理解错了你的问题。如果您想列出所有属性,包括所有子项目以及根项目,那么您可以创建一个构建文件,如下所示:
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
方法来以漂亮的方式打印所有属性。
根据 this Gradle Forum response, the properties task is not running for subprojects since the impliesSubProjects
property of the properties task is true
in the property implementation:
The task is configured to ignore subproject tasks by the HelpTasksPlugin
using an internal API
[…]
Then TaskNameResolver
does not look at subprojects for the task if impliesSubProjects
is true
.
实验表明,可以在构建文件中配置 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
and is not part of the public Task
API (see Avoid using internal Gradle APIs 有关内部 API 的更多详细信息)。因此,如链接论坛回复中所述,这不适用于构建:
keep in mind that it’s an internal implementation detail not intended to be used by builds and there are no guarantees it will keep working in future Gradle releases.
但是,如果一次性 属性 比较不是构建的持久部分,这种意外使用可能是可以接受的。
我想查看 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
[...]
但是,我真正想做的是一次列出给定项目及其所有子项目的属性。
我有点惊讶在根级别调用任务只提供根级别属性。这似乎与有关 executing tasks by name in a multi-project build:
的 Gradle 文档相矛盾The command
gradle test
will execute thetest
task in any subprojects, relative to the current working directory, that have that task. If you run the command from the root project directory, you’ll runtest
in api, shared, services:shared and services:webservice. If you run the command from the services project directory, you’ll only execute the task in services:shared and services:webservice.The basic rule behind Gradle’s behavior is: execute all tasks down the hierarchy which have this name. Only complain if there is no such task found in any of the subprojects traversed.
如何一次列出项目及其子项目的所有属性?作为奖励,为什么根级别的 properties
任务 运行 也不是子项目的 运行ning?我正在使用当前最新版本的 Gradle (6.7.1)。
可能是我理解错了你的问题。如果您想列出所有属性,包括所有子项目以及根项目,那么您可以创建一个构建文件,如下所示:
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
方法来以漂亮的方式打印所有属性。
根据 this Gradle Forum response, the properties task is not running for subprojects since the impliesSubProjects
property of the properties task is true
in the property implementation:
The task is configured to ignore subproject tasks by the
HelpTasksPlugin
using an internal API[…]
Then
TaskNameResolver
does not look at subprojects for the task ifimpliesSubProjects
istrue
.
实验表明,可以在构建文件中配置 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
and is not part of the public Task
API (see Avoid using internal Gradle APIs 有关内部 API 的更多详细信息)。因此,如链接论坛回复中所述,这不适用于构建:
keep in mind that it’s an internal implementation detail not intended to be used by builds and there are no guarantees it will keep working in future Gradle releases.
但是,如果一次性 属性 比较不是构建的持久部分,这种意外使用可能是可以接受的。