Ten*_*r04 3 jvm gradle gradle-kotlin-dsl
这是针对 JVM 应用程序的。
我正在创建一个属性文件,其中包含要在应用程序运行时使用的版本。我在基础项目中编写了这个任务build.gradle.kts:
allprojects {
//...
tasks.register("createVersionPropertiesFile") {
group = "build"
doLast {
val resourcesDir = File("$buildDir/resources/main").apply { mkdirs() }
val resource = File(resourcesDir, "version.properties")
resource.writeText("version=${project.version}")
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我独立运行此任务,它会按我的预期创建文件。
为了在构建期间运行任务,我将其放入应用程序模块中build.gradle.kts:
tasks.processResources {
dependsOn += tasks["createVersionPropertiesFile"]
}
Run Code Online (Sandbox Code Playgroud)
然而,在构建过程中,资源目录实际上被删除而不是创建(或者如果是的话,它会在构建完成之前再次被删除)。因此,应用程序运行时找不到资源。
如何设置此任务在构建过程的适当阶段运行?
我知道另一种策略是在源代码的实际资源目录中创建资源文件,但我不想用这个自动生成的文件弄脏签入的源代码。我希望它只是构建的一部分。
dirbuild/resources/是任务的输出processResources目录,因此(根据 Javadoc)任何其他文件都将被自动删除。
有一种更好的方法来连接任务,以便 Gradle 会将其识别为源文件,并使 Gradle 自动运行该文件。
为了简单起见,我将演示如何在没有配置的情况createVersionPropertiesFile下在单个.build.gradle.ktsallprojects {}
首先,确保在生成任务中注册输出目录以及输入。这可以使用运行时 API来完成。任务有一个tempDirectory非常适合用作输出目录的默认目录,但如果您愿意,也可以使用自定义目录。
项目版本应设置为任务的输入属性,以便 Gradle 知道如果值更改需要重新运行任务。为了与Gradle的配置缓存兼容(project任务执行期间不得使用),它应该被定义为val任务配置块内部。
val createVersionPropertiesFileTask = tasks.register("createVersionPropertiesFile") {
group = "build"
// define a local val, to be compatible with Configuration Cache
val projectVersion = project.version
// Register the project version as a task input, so Gradle can cache the task
inputs.property("projectVersion", projectVersion)
// tell Gradle about the output directory
outputs.dir(temporaryDir)
doLast {
val resource = File(temporaryDir, "version.properties")
resource.writeText("version=${projectVersion}")
}
}
Run Code Online (Sandbox Code Playgroud)
这些文档详细解释了为什么注册输入和输出是有益的。这里重要的是,借助 Gradle 的 Provider API,任务可以转换为 file-provider。
Java 项目是使用SourceSet组织的。这些都预先配置了我们所知道和喜爱的src/main/java和src/test/resources,并且可以添加更多:
sourceSets {
main {
java {
// add an additional source directory
srcDir("$buildDir/some-extra-sources/java")
}
resources {
// add an additional resource directory
srcDir("$buildDir/some-extra-sources/resources")
}
}
}
Run Code Online (Sandbox Code Playgroud)
虽然您可以将输出目录硬编码为createVersionPropertiesFile附加资源目录,但 Gradle 不知道它需要运行任务来生成文件。我们可以进行二买一的交易:添加一个新的资源目录,并告诉 Gradle 它需要运行该任务。
sourceSets {
main {
resources {
// add a new resource dir that is produced by the task
srcDir(createVersionPropertiesFileTask.map { it.temporaryDir })
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,无需添加任何dependsOn(createVersionPropertiesFileTask)- 因此您可以删除tasks.processResources.
现在,当您运行时,您将看到任务./gradlew build将生成您的自定义文件。build/resourcesprocessResources
如果您使用 IntelliJ,还有一个小好处:它将在项目资源管理器侧栏中突出显示新的资源目录。
您可能会发现有问题的是使用allprojects {}为所有项目配置此任务。(还有一些其他 原因 导致我们allprojects {}不subprojects {}鼓励。)
相反,考虑创建一个约定插件,使用buildSrccreateVersionPropertiesFileTask通过几个简单的步骤创建和配置:
创建buildSrc/build.gradle.kts并且,由于 buildSrc 实际上是一个独立的项目,buildSrc/settings.gradle.kts
应用kotlin-dsl插件buildSrc/build.gradle.kts,这样我们就可以制作预编译脚本插件了。
使用上面提供的配置为您的约定创建一个文件。
// ./buildSrc/src/main/kotlin/my-java-conventions.gradle.kts
plugins {
java
}
val createVersionPropertiesFileTask = tasks.register("createVersionPropertiesFile") {
group = "build"
val projectVersion = project.version
inputs.property("projectVersion", projectVersion)
outputs.dir(temporaryDir)
doLast {
val resource = File(temporaryDir, "version.properties")
resource.writeText("version=${projectVersion}")
}
}
sourceSets {
main {
resources {
srcDir(createVersionPropertiesFileTask.map { it.temporaryDir })
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在所有子项目中,您可以在需要的地方专门应用约定插件 - 不再需要allprojects {}
// ./app-subproject/build.gradle.kts
plugins {
`my-java-conventions`
}
Run Code Online (Sandbox Code Playgroud)
由于您正在生成.properties文件,因此您可能还需要考虑使用内置任务类型来生成属性 - WriteProperties。它有一些实用程序用于添加多个属性,并确保生成的文件是可重复生成的(以便 Gradle 的缓存运行良好。)
| 归档时间: |
|
| 查看次数: |
1233 次 |
| 最近记录: |