Gradle 5 Kotlin DSL:多模块项目中的常见任务和Maven工件



我真的很欣赏Gradle 5,尤其是与新的Kotlin DSL相结合,但我很难(在我看来(用Gradle运行一个非常、非常简单和常见的构建。

任务

在Maven默认目录布局中发布一个Java库,其中包含多个相互依赖的子模块作为高质量的Maven工件/存储库RY(。

因此:有一个根项目作为保护伞,定义&包含所有通用配置(实际上除了真正的依赖项之外的所有配置(。

我目前的挣扎

我将我目前的"结果"移植到Github上的一个示例项目中,并在Gradle论坛上提出了这个问题。

目前,我未能声明在中心构建中提供标准-sources-javadoc工件的必要任务。

例如,在寻找基于Kotlin DSL的解决方案时,您会发现这三种"解决方案">在多模块场景中都不起作用

  • https://stackoverflow.com/a/48070667
  • https://stackoverflow.com/a/52596969/1237653
  • 甚至官方的"Maven Publish"文档也只能在单个模块场景中工作

不完全解(/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)
}
}
}
}

几个注意事项:

  • 既然可以执行类型安全的apply<T>(),为什么要使用基于Stringapply
  • 为什么要在dependencies中的stings上使用调用,而您可以使用委派,这不那么麻烦,而且可以更好地重构
  • 考虑使用implementation而不是compile

为什么sourceSets不能在多模块项目中工作?

当您使用Kotlin DSL时,它会根据应用的插件为项目生成访问者。这是一个分两步的过程:首先Gradle处理插件(这就是为什么建议将它们放在plugins块中(并生成访问器,然后您可以在代码中使用它们(访问器被生成为ProjectNamedDomainObjectContainer等的Kotlin扩展(。但是,如果您正在配置子项目,则存在两个问题:

  • 父项目在子项目之前求值,因此子项目的扩展在父项目中是未知的
  • 应用于父级和子级的插件集是不同的,您需要在父级中使用子级访问器

sourceSets是Kotlin DSL为儿童生成的访问器之一。它只是在parent中不可用。您可以自己尝试:在subprojects中仅应用java插件。sourceSets将在子级构建脚本中可用,但在父级中不可用。

这也是为什么您可以在子级中使用java,但在父级中配置时必须使用configure<JavaPluginExtension>

但是您可以使用委托来获取域对象的引用,比如任务、源集、配置等等

最新更新