【问题标题】:Using a Custom SourceSet in Gradle在 Gradle 中使用自定义 SourceSet
【发布时间】:2020-06-08 15:17:33
【问题描述】:

根据this from the official docs和this SO answer,定义一个新的源集应该像(在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) }
    })
}

这个胖 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 的所有三个标准.

【问题讨论】:

    标签: kotlin gradle build.gradle


    【解决方案1】:

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

    from(sourceSets["demo"].output)
    

    在使用sourceSets.main 时必须使用get() 的原因是因为你得到了一个NamedDomainObjectProvider<SourceSet>,它包装源集。

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

    1. 创建时:

      val demo by sourceSets.creating { /* configure */ }
      
    2. 或者在创建它之后的一段时间:

      val demo by sourceSets
      

    【讨论】:

      猜你喜欢
      • 2016-09-16
      • 2013-08-11
      • 2023-03-17
      • 2015-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-06
      相关资源
      最近更新 更多