拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 Gradle sourceSets来源集

Gradle sourceSets来源集

白鹭 - 2021-11-24 652 0 0

1.概述

源代码集为我们提供了一种在Gradle项目中构建源代码的强大方法。

在本快速教程中,我们将了解如何使用它们。

2.默认来源集

在进入默认值之前,让我们首先解释什么是源集。顾名思义,源集代表源文件的逻辑分组

我们将介绍Java项目的配置,但是这些概念也适用于其他Gradle项目类型。

2.1 默认项目布局

让我们从一个简单的项目结构开始:

source-sets

 ├── src

 │ ├── main

 │ │ └── java

 │ │ ├── SourceSetsMain.java

 │ │ └── SourceSetsObject.java

 │ └── test

 │ └── java

 │ └── SourceSetsTest.java

 └── build.gradle

现在让我们看一下build.gradle

apply plugin : "java"

 description = "Source Sets example"

 test {

 testLogging {

 events "passed", "skipped", "failed"

 }

 }

 dependencies {

 implementation('org.apache.httpcomponents:httpclient:4.5.12')

 testImplementation('junit:junit:4.12')

 }

Java插件假定**src/main/javasrc/test/java为默认源目录**.

让我们设计一个简单的实用程序任务:

task printSourceSetInformation(){

 doLast{

 sourceSets.each { srcSet ->

 println "["+srcSet.name+"]"

 print "-->Source directories: "+srcSet.allJava.srcDirs+"\n"

 print "-->Output directories: "+srcSet.output.classesDirs.files+"\n"

 println ""

 }

 }

 }

我们在这里仅打印一些源集属性。我们总是可以查看完整的JavaDoc以获得更多信息。

让我们运行它,看看会得到什么:

$ ./gradlew printSourceSetInformation



 > Task :source-sets:printSourceSetInformation

 [main]

 -->Source directories: [.../source-sets/src/main/java]

 -->Output directories: [.../source-sets/build/classes/java/main]



 [test]

 -->Source directories: [.../source-sets/src/test/java]

 -->Output directories: [.../source-sets/build/classes/java/test]

注意,我们有两个默认的源集: maintest

2.2 默认配置

**Java插件还会自动为我们创建一些默认的Gradle配置**。

它们遵循特殊的命名约定: <sourceSetName><configurationName>

我们使用它们在build.gradle声明依赖项:

dependencies {

 implementation('org.apache.httpcomponents:httpclient:4.5.12')

 testImplementation('junit:junit:4.12')

 }

注意,我们指定了implementation而不是mainImplementation 。这是命名约定的例外。

默认情况下, testImplementation配置扩展implementation并继承其所有依赖项和输出

让我们改进帮助程序任务,看看这是关于什么的:

task printSourceSetInformation(){



 doLast{

 sourceSets.each { srcSet ->

 println "["+srcSet.name+"]"

 print "-->Source directories: "+srcSet.allJava.srcDirs+"\n"

 print "-->Output directories: "+srcSet.output.classesDirs.files+"\n"

 print "-->Compile classpath:\n"

 srcSet.compileClasspath.files.each {

 print " "+it.path+"\n"

 }

 println ""

 }

 }

 }

让我们看一下输出:

[main]

 // same output as before

 -->Compile classpath:

 .../httpclient-4.5.12.jar

 .../httpcore-4.4.13.jar

 .../commons-logging-1.2.jar

 .../commons-codec-1.11.jar



 [test]

 // same output as before

 -->Compile classpath:

 .../source-sets/build/classes/java/main

 .../source-sets/build/resources/main

 .../httpclient-4.5.12.jar

 .../junit-4.12.jar

 .../httpcore-4.4.13.jar

 .../commons-logging-1.2.jar

 .../commons-codec-1.11.jar

 .../hamcrest-core-1.3.jar

test源集在其编译类路径中main的输出,还包括其依赖项。

接下来,让我们创建我们的单元测试:

public class SourceSetsTest {



 @Test

 public void whenRun_ThenSuccess() {



 SourceSetsObject underTest = new SourceSetsObject("lorem","ipsum");



 assertThat(underTest.getUser(), is("lorem"));

 assertThat(underTest.getPassword(), is("ipsum"));

 }

 }

在这里,我们测试一个简单的POJO,该POJO存储两个值。我们可以直接使用它,因为**main输出在我们的test类路径中**。

接下来,让我们从Gradle中运行它:

./gradlew clean test



 > Task :source-sets:test



 com.baeldung.test.SourceSetsTest > whenRunThenSuccess PASSED

3.自定义来源集

到目前为止,我们已经看到了一些明智的默认设置。但是,实际上,我们经常需要自定义源集,尤其是对于集成测试。

那是因为我们可能只想在集成测试类路径上拥有特定的测试库。我们还可能希望独立于单元测试执行它们。

3.1 定义自定义源集

让我们为集成测试设计一个单独的源目录:

source-sets

 ├── src

 │ └── main

 │ ├── java

 │ │ ├── SourceSetsMain.java

 │ │ └── SourceSetsObject.java

 │ ├── test

 │ │ └── SourceSetsTest.java

 │ └── itest

 │ └── SourceSetsITest.java

 └── build.gradle

接下来,让**我们使用sourceSets构造build.gradle**进行配置:

sourceSets {

 itest {

 java {

 }

 }

 }

 dependencies {

 implementation('org.apache.httpcomponents:httpclient:4.5.12')

 testImplementation('junit:junit:4.12')

 }

 // other declarations omitted

注意,我们没有指定任何自定义目录。这是因为我们的文件夹与新的源集( itest )的名称匹配。

我们可以**srcDirs属性包含的目录**:

sourceSets{

 itest {

 java {

 srcDirs("src/itest")

 }

 }

 }

从一开始就还记得我们的帮助任务吗?让我们重新运行它,看看它显示了什么:

$ ./gradlew printSourceSetInformation



 > Task :source-sets:printSourceSetInformation

 [itest]

 -->Source directories: [.../source-sets/src/itest/java]

 -->Output directories: [.../source-sets/build/classes/java/itest]

 -->Compile classpath:

 .../source-sets/build/classes/java/main

 .../source-sets/build/resources/main



 [main]

 // same output as before



 [test]

 // same output as before

3.2 分配源集特定的依存关系

还记得默认配置吗?现在,我们还为itest源集获取了一些配置。

让我们使用itestImplementation分配一个新的依赖项

dependencies {

 implementation('org.apache.httpcomponents:httpclient:4.5.12')

 testImplementation('junit:junit:4.12')

 itestImplementation('com.google.guava:guava:29.0-jre')

 }

这仅适用于集成测试。

让我们修改之前的测试并将其添加为集成测试:

public class SourceSetsItest {



 @Test

 public void givenImmutableList_whenRun_ThenSuccess() {



 SourceSetsObject underTest = new SourceSetsObject("lorem", "ipsum");

 List someStrings = ImmutableList.of("Baeldung", "is", "cool");



 assertThat(underTest.getUser(), is("lorem"));

 assertThat(underTest.getPassword(), is("ipsum"));

 assertThat(someStrings.size(), is(3));

 }

 }

为了能够运行它,我们需要定义一个使用已编译输出的自定义测试任务

// source sets declarations



 // dependencies declarations



 task itest(type: Test) {

 description = "Run integration tests"

 group = "verification"

 testClassesDirs = sourceSets.itest.output.classesDirs

 classpath = sourceSets.itest.runtimeClasspath

 }

这些声明在配置阶段**进行评估。结果,它们的顺序很重要**。

例如,在声明此声明之前,我们无法引用itest

让我们看看如果运行测试会发生什么:

$ ./gradlew clean itest



 // some compilation issues



 FAILURE: Build failed with an exception.



 * What went wrong:

 Execution failed for task ':source-sets:compileItestJava'.

 > Compilation failed; see the compiler error output for details.

与之前的运行不同,这次我们遇到编译错误。所以发生了什么事?

这个新的源集将创建一个独立的配置。

换句话说, itestImplementation不会继承JUnit依赖关系,也不会获取main的输出。

让我们在Gradle配置中解决此问题:

sourceSets{

 itest {

 compileClasspath += sourceSets.main.output

 runtimeClasspath += sourceSets.main.output

 java {

 }

 }

 }



 // dependencies declaration

 configurations {

 itestImplementation.extendsFrom(testImplementation)

 itestRuntimeOnly.extendsFrom(testRuntimeOnly)

 }

现在,让我们重新运行集成测试:

$ ./gradlew clean itest



 > Task :source-sets:itest



 com.baeldung.itest.SourceSetsItest > givenImmutableList_whenRun_ThenSuccess PASSED

测试通过。

3.3 Eclipse IDE处理

到目前为止,我们已经看到了如何直接使用Gradle处理源集。但是,大多数时候,我们将使用IDE(例如Eclipse)。

导入项目时,会遇到一些编译问题:

Gradle来源集

但是,如果我们从Gradle运行集成测试,则不会出现任何错误:

$ ./gradlew clean itest



 > Task :source-sets:itest



 com.baeldung.itest.SourceSetsItest > givenImmutableList_whenRun_ThenSuccess PASSED

所以发生了什么事?在这种情况下, guava依赖项属于itestImplementation

不幸的是, Eclipse Buildship Gradle插件不能很好地处理这些自定义配置

让我们**build.gradle修复此**问题:

apply plugin: "eclipse"



 // previous declarations



 eclipse {

 classpath {

 plusConfigurations+=[configurations.itestCompileClasspath]

 }

 }

让我们解释一下我们在这里做了什么。我们将配置附加到Eclipse类路径中。

如果我们刷新项目,则编译问题就消失了。

但是,这种方法有一个缺点:IDE不能区分配置。

这意味着我们可以轻松地在test源中guava (我们特别想避免这种情况)。

4 结论

在本教程中,我们介绍了Gradle源集的基础。
然后,我们解释了定制源集如何工作以及如何在Eclipse中使用它们。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *