我真的很欣赏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>()
,为什么要使用基于String
的apply
- 为什么要在
dependencies
中的stings上使用调用,而您可以使用委派,这不那么麻烦,而且可以更好地重构 - 考虑使用
implementation
而不是compile
为什么sourceSets
不能在多模块项目中工作?
当您使用Kotlin DSL时,它会根据应用的插件为项目生成访问者。这是一个分两步的过程:首先Gradle处理插件(这就是为什么建议将它们放在plugins
块中(并生成访问器,然后您可以在代码中使用它们(访问器被生成为Project
、NamedDomainObjectContainer
等的Kotlin扩展(。但是,如果您正在配置子项目,则存在两个问题:
- 父项目在子项目之前求值,因此子项目的扩展在父项目中是未知的
- 应用于父级和子级的插件集是不同的,您需要在父级中使用子级访问器
sourceSets
是Kotlin DSL为儿童生成的访问器之一。它只是在parent中不可用。您可以自己尝试:在subprojects
中仅应用java
插件。sourceSets
将在子级构建脚本中可用,但在父级中不可用。
这也是为什么您可以在子级中使用java
,但在父级中配置时必须使用configure<JavaPluginExtension>
。
但是您可以使用委托来获取域对象的引用,比如任务、源集、配置等等