Gradle 5 Kotlin DSL:多模块项目中的常见任务和 Maven 工件
Gradle 5 Kotlin DSL: Common Tasks & Maven Artifacts in multi-modules projects
我真的很想感谢 Gradle 5,尤其是与新的 Kotlin DSL 结合使用时,但我很难(在我看来)获得一个非常非常简单和通用的构建运行 Gradle.
任务
在 Maven 默认目录布局 as high-质量 Maven artifacts/repository 在一个切中要点的简单 Gradle 构建中(即 DRY)。
因此:有一个根项目作为保护伞,它定义并包含所有常用配置(实际上除了真正的依赖项之外的所有配置)。
我目前的挣扎
我将当前的 "results" 移植到 a sample project on Github and asked this question in the Gradle forum already。
目前我没有声明在我的 central 构建中提供标准 -sources
和 -javadoc
工件的必要任务。
例如,这三个 "solutions",你会在寻找基于 Kotlin DSL 的解决方案时找到它们 在多模块场景中都不会(不再)工作 :
- 甚至官方"Maven Publish" documentation也只能在单模块场景下工作。
不完整的解决方案(/build.gradle.kts
)
完整示例参见 Github:https://github.com/bentolor/gradle-maven-multimodule-kotlindsl
subprojects {
apply(plugin = "java-library")
apply(plugin = "maven-publish")
group = "de.bentolor.sampleproject"
version = "0.1.0"
repositories {
jcenter()
}
dependencies {
// Dependencies used in EVERY module
"compile"("commons-logging:commons-logging:1.2")
"testImplementation"("junit:junit:4.12")
}
tasks {
// not working
/*register("sourcesJar", Jar::class.java) {
from(sourceSets.main.get().allJava)
classifier = "sources"
}*/
// not working, eiher
/* task<Jar>("sourcesJar") {
from(sourceSets.main.get().allJava)
classifier = "sources"
} */
}
configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
configure<PublishingExtension> {
publications {
create<MavenPublication>(project.name) {
from(components["java"])
// won't work, beause inaccessible declaration in `tasks{}`-Block
//add("archives", javadocJar)
//add("archives", sourcesJar)
}
}
repositories {
mavenLocal()
}
}
}
示例子模块 /module2/build.gradle.kts
group = "de.bentolor.sampleproject.module2"
dependencies {
compile(project(":module1"))
}
试试这个:
subprojects {
apply<JavaLibraryPlugin>()
apply<MavenPublishPlugin>()
group = "de.bentolor.sampleproject"
version = "0.1.0"
repositories {
jcenter()
}
dependencies {
val implementation by configurations
val testImplementation by configurations
implementation("commons-logging:commons-logging:1.2")
testImplementation("junit:junit:4.12")
}
// This will work, but as long as these tasks are need only for publishing you can declare them inplace later where you need
// tasks {
// val sourcesJar by creating(Jar::class) {
// val sourceSets: SourceSetContainer by project
// from(sourceSets["main"].allJava)
// classifier = "sources"
// }
// val javadoc by getting(Javadoc::class)
// val javadocJar by creating(Jar::class) {
// from(javadoc)
// classifier = "javadoc"
// }
// }
configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
configure<PublishingExtension> {
publications {
create<MavenPublication>(project.name) {
from(components["java"])
// If you configured them before
// val sourcesJar by tasks.getting(Jar::class)
// val javadocJar by tasks.getting(Jar::class)
val sourcesJar by tasks.creating(Jar::class) {
val sourceSets: SourceSetContainer by project
from(sourceSets["main"].allJava)
classifier = "sources"
}
val javadocJar by tasks.creating(Jar::class) {
from(tasks.get("javadoc"))
classifier = "javadoc"
}
artifact(sourcesJar)
artifact(javadocJar)
}
}
}
}
一些注意事项:
- 为什么要使用基于
String
的 apply
,当您可以执行 type-safe apply<T>()
时?
- 为什么在
dependencies
中对 stings 使用调用,当你可以使用委托时,委托更少且可重构性更好。
- 考虑使用
implementation
instead of compile
为什么 sourceSets
没有在 multi-module 项目中工作?
当您使用 Kotlin DSL 时,它会根据应用的插件为项目生成访问器。这是一个 two-step 过程:首先 Gradle 处理插件(这就是为什么建议将它们放在 plugins
块中)并生成访问器,然后您可以在代码中使用它们(访问器生成为Project
、NamedDomainObjectContainer
等的 Kotlin 扩展)。但是如果你配置子项目有两个问题:
- Parent 项目在 child 之前评估,因此 child 的扩展在 parent 中未知。
- 应用于parent和child的插件集不同,您需要在parent.
中使用children访问器
sourceSets
是 Kotlin DSL 为 children 生成的访问器之一。它只是在 parent 中不可用。你可以自己试试:在subprojects
中只应用java
插件。 sourceSets
将在 children 构建脚本中可用,但在 parent.
中不可用
这也是为什么在children中可以使用java
,而在parent中配置时必须使用configure<JavaPluginExtension>
的原因。
但您可以使用委托获取域 objects 的引用,例如任务、源集、配置等。
我真的很想感谢 Gradle 5,尤其是与新的 Kotlin DSL 结合使用时,但我很难(在我看来)获得一个非常非常简单和通用的构建运行 Gradle.
任务
在 Maven 默认目录布局 as high-质量 Maven artifacts/repository 在一个切中要点的简单 Gradle 构建中(即 DRY)。
因此:有一个根项目作为保护伞,它定义并包含所有常用配置(实际上除了真正的依赖项之外的所有配置)。
我目前的挣扎
我将当前的 "results" 移植到 a sample project on Github and asked this question in the Gradle forum already。
目前我没有声明在我的 central 构建中提供标准 -sources
和 -javadoc
工件的必要任务。
例如,这三个 "solutions",你会在寻找基于 Kotlin DSL 的解决方案时找到它们 在多模块场景中都不会(不再)工作 :
- 甚至官方"Maven Publish" documentation也只能在单模块场景下工作。
不完整的解决方案(/build.gradle.kts
)
完整示例参见 Github:https://github.com/bentolor/gradle-maven-multimodule-kotlindsl
subprojects {
apply(plugin = "java-library")
apply(plugin = "maven-publish")
group = "de.bentolor.sampleproject"
version = "0.1.0"
repositories {
jcenter()
}
dependencies {
// Dependencies used in EVERY module
"compile"("commons-logging:commons-logging:1.2")
"testImplementation"("junit:junit:4.12")
}
tasks {
// not working
/*register("sourcesJar", Jar::class.java) {
from(sourceSets.main.get().allJava)
classifier = "sources"
}*/
// not working, eiher
/* task<Jar>("sourcesJar") {
from(sourceSets.main.get().allJava)
classifier = "sources"
} */
}
configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
configure<PublishingExtension> {
publications {
create<MavenPublication>(project.name) {
from(components["java"])
// won't work, beause inaccessible declaration in `tasks{}`-Block
//add("archives", javadocJar)
//add("archives", sourcesJar)
}
}
repositories {
mavenLocal()
}
}
}
示例子模块 /module2/build.gradle.kts
group = "de.bentolor.sampleproject.module2"
dependencies {
compile(project(":module1"))
}
试试这个:
subprojects {
apply<JavaLibraryPlugin>()
apply<MavenPublishPlugin>()
group = "de.bentolor.sampleproject"
version = "0.1.0"
repositories {
jcenter()
}
dependencies {
val implementation by configurations
val testImplementation by configurations
implementation("commons-logging:commons-logging:1.2")
testImplementation("junit:junit:4.12")
}
// This will work, but as long as these tasks are need only for publishing you can declare them inplace later where you need
// tasks {
// val sourcesJar by creating(Jar::class) {
// val sourceSets: SourceSetContainer by project
// from(sourceSets["main"].allJava)
// classifier = "sources"
// }
// val javadoc by getting(Javadoc::class)
// val javadocJar by creating(Jar::class) {
// from(javadoc)
// classifier = "javadoc"
// }
// }
configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
configure<PublishingExtension> {
publications {
create<MavenPublication>(project.name) {
from(components["java"])
// If you configured them before
// val sourcesJar by tasks.getting(Jar::class)
// val javadocJar by tasks.getting(Jar::class)
val sourcesJar by tasks.creating(Jar::class) {
val sourceSets: SourceSetContainer by project
from(sourceSets["main"].allJava)
classifier = "sources"
}
val javadocJar by tasks.creating(Jar::class) {
from(tasks.get("javadoc"))
classifier = "javadoc"
}
artifact(sourcesJar)
artifact(javadocJar)
}
}
}
}
一些注意事项:
- 为什么要使用基于
String
的apply
,当您可以执行 type-safeapply<T>()
时? - 为什么在
dependencies
中对 stings 使用调用,当你可以使用委托时,委托更少且可重构性更好。 - 考虑使用
implementation
instead ofcompile
为什么 sourceSets
没有在 multi-module 项目中工作?
当您使用 Kotlin DSL 时,它会根据应用的插件为项目生成访问器。这是一个 two-step 过程:首先 Gradle 处理插件(这就是为什么建议将它们放在 plugins
块中)并生成访问器,然后您可以在代码中使用它们(访问器生成为Project
、NamedDomainObjectContainer
等的 Kotlin 扩展)。但是如果你配置子项目有两个问题:
- Parent 项目在 child 之前评估,因此 child 的扩展在 parent 中未知。
- 应用于parent和child的插件集不同,您需要在parent. 中使用children访问器
sourceSets
是 Kotlin DSL 为 children 生成的访问器之一。它只是在 parent 中不可用。你可以自己试试:在subprojects
中只应用java
插件。 sourceSets
将在 children 构建脚本中可用,但在 parent.
这也是为什么在children中可以使用java
,而在parent中配置时必须使用configure<JavaPluginExtension>
的原因。
但您可以使用委托获取域 objects 的引用,例如任务、源集、配置等。