在 Gradle 中使用自定义 SourceSet

Using a Custom SourceSet in Gradle

根据 this from the official docs and ,定义一个新的源集应该像(在 kotlin 中)一样简单:

sourceSets {
    create("demo") {
        compileClasspath += sourceSets.main.get().output
    }
}

第二个参考也明确声称现在可以在构建 jar 时使用它。 然而,虽然上面没有抛出错误,但实际上是在尝试使用新的源集任何地方都可以。最小示例(使用 gradle init -> "kotlin application" 和项目名称 "foobar" 生成):

plugins {
    id("org.jetbrains.kotlin.jvm").version("1.3.21")
    application
}

repositories {
    jcenter()
}

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}

application {
    mainClassName = "foobar.AppKt"
}

sourceSets {
    create("demo") {
        compileClasspath += sourceSets.main.get().output
    }
}

我删除了 test 源集的配置,因为它与此处无关。 src 目录看起来像这样(有点不标准,但我认为适合讨论):

src
├── demo
│   └── Demo.kt
└── main
    └── foobar
        └── App.kt

理想情况下,我希望有完全独立的源代码树(但这个问题不是专门针对那个)。相对于上面的配置,这个构建是有意义的,但这并不是真正的目标。为此,我想添加一两个自定义 jar。1

不幸的是,demo 源集无法在 gradle 脚本中引用。

val jar by tasks.getting(Jar::class) {
    manifest { attributes["Main-Class"] = "DemoKt" }

    // HERE IS THE PROBLEM:
    from(sourceSets["demo"].get().output)
    dependsOn(configurations.runtimeClasspath)
    from({
        configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
    })
}

这个fat jar任务定义是taken from the gradle docs,我以前用过很多
照原样,gradle 窒息:

Script compilation errors:


  Line 28:      from(sourceSets["demo"].get().output)
                                    ^ Unresolved reference.

如果我将该行更改为:

from(sourceSets.demo.get().output)

sourceSets.main一起使用的语法是什么,那么错误就变成了:

 Line 28:      from(sourceSets.demo.get().output)
                            ^ Unresolved reference: demo

我应该如何使用自定义源集?


  1. 我知道 gradle subproject 模式并用它做了很多相同的事情,但我更喜欢简单的独立源集解决方案,我认为它满足所有要求提到的三个标准 in that doc.

sourceSets 属性(Project 的扩展 属性)returns 扩展 NamedDomainObjectContainer<SourceSet>SourceSetContainer。后一个接口定义了 get(String) (运算符扩展函数),它允许您使用 ["..."] 语法。该方法 returns T 直接,这意味着您应该只使用:

from(sourceSets["demo"].output)

在使用 sourceSets.main 时必须使用 get() 的原因是因为您得到的 NamedDomainObjectProvider<SourceSet> 包装 源集.

您还可以通过委托获取自定义源集

  1. 创建时:

    val demo by sourceSets.creating { /* configure */ }
    
  2. 或创建后的某个时间:

    val demo by sourceSets