Gradle sourceSets來源集

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中使用它們。