2013-11-15 60 views
25

至於現在我們有一個項目結構,其中包含單個源文件夾src,其中包含三個模塊的源代碼。我想要做的是:單個來源文件夾中的Gradle多個罐子

1)編譯源代碼。這很容易用sourceSets定義:

sourceSets { 
    main { 
     java { 
      srcDir 'src' 
     } 
    } 
} 

2)將編譯結果放入三個罐子中。現在通過三個獨立的任務

我這樣做::我通過三個 '罐子' 類型的任務,這樣做

  • util.jar

    task utilJar(type: Jar) { 
        from(sourceSets.main.output) { 
         include "my/util/package/**" 
        } 
    } 
    
  • client.jar中

    task clientJar(type: Jar) { 
        from(sourceSets.main.output) { 
         include "my/client/package/**" 
        } 
    } 
    
  • server.jar

    task serverJar(type: Jar) { 
        from(sourceSets.main.output) { 
         include "**" 
        } 
        excludes.addAll(utilJar.includes) 
        excludes.addAll(clientJar.includes) 
    } 
    

的事情是,server.jar應包含不包含在client.jarutil.jar所有類。在ant構建腳本中,我們通過使用difference ant任務來解決此問題。如何在gradle中完成這項工作(我目前的方法無效)?

也許我的方法是完全錯誤的。請指教。

P.S.至於現在我們不能更改項目源代碼文件夾結構。

回答

26

我會在這裏發佈我的工作解決方案作爲答案(我在Gradle的論壇上有提示)。

gradle中的範圍是非常奇怪的事情:)我認爲每個任務定義都會創建一些'Task'類的對象,在這種情況下就像'JarTask'。然後,我可以從我的build.gradle腳本中的任何地方訪問該類的任何屬性。但是,我發現唯一可以看到包含在jar文件中的模式的地方 - 在任務的from塊內。所以現在我的工作的解決方案是:

1)定義項目級集合包含模式從server.jar

2除外)排除所有圖案serverJar任務from塊。

請參考下面

sourceSets { 
    main { 
     java { 
      srcDir 'src' 
     } 
    } 
} 

// holds classes included into client.jar and util.jar, so they are to be excluded from server.jar 
ext.serverExcludes = [] 

// util.jar 
task utilJar(type: Jar) { 
    from(sourceSets.main.output) { 
     include "my/util/package/**" 
     project.ext.serverExcludes.addAll(includes) 
    } 
} 

// client.jar 
task clientJar(type: Jar) { 
    from(sourceSets.main.output) { 
     include "my/client/package/**" 
     project.ext.serverExcludes.addAll(includes) 
    } 
} 

// server.jar 
task serverJar(type: Jar) { 
    from(sourceSets.main.output) { 
     exclude project.ext.serverExcludes 
    } 
} 
+0

這很好,但是您如何引用其他項目的單獨'.jar'文件 - 例如你怎麼能把'client.jar'放到另一個子項目中呢? – z0r

+0

@z0r我們只是將工件發佈到存儲庫,然後將它們用作子項目中的依賴關係。 P.S.對於延遲迴復抱歉。 – vitalidze

16

我認爲這種做法是錯誤的。我建議製作一個包含3個子項目的項目。

project 
- util 
- server (depends on util) 
- client (depends on util) 

如果由於某種原因,你不能改變的階級結構使用這樣的編譯文件:

settings.gradle

include 'util', 'client', 'server' 

的build.gradle

subprojects { 
    apply plugin: 'java' 
} 

project(':util') { 
    sourceSets { 
     main { 
      java { 
       srcDir '../src' 
       include 'util/**' 
      } 
     } 
    } 
} 

project(':server') { 
    sourceSets { 
     main { 
      java { 
       srcDir '../src' 
       include 'server/**' 
      } 
     } 
    } 
    dependencies { 
     compile project(':util') 
    } 
} 

project(':client') { 
    sourceSets { 
     main { 
      java { 
       srcDir '../src' 
       include 'client/**' 
      } 
     } 
    } 
    dependencies { 
     compile project(':util') 
    } 
} 

你仍然需要子項目的目錄,但是你可以根據需要在一個地方找到源代碼。

當您運行gradle assemble時,您將擁有3個帶有單獨的一組類的罐子。這個解決方案的優點是我們使用正確的依賴關係創建了適當的Gradle多模塊項目,而不僅僅是構建罐子的任務。

請閱讀Multi-Project Builds

+0

感謝您的評論。我曾考慮過這種方法,但根本不需要改變目錄結構。主要原因是我們有很多SVN分支(超過五十個),在目錄結構變化(你知道,樹衝突)之後合併它們應該是一個真正的痛苦。另一個原因是'util'和'client'互相依賴,所以我猜他們應該放在一個單獨的模塊中,這會帶來同樣的問題。我知道在源代碼結構設計中這是一團糟,但我相信gradle可以完成螞蟻可以做的所有事情:) – vitalidze

+1

@vitalidze我提出的解決方案並沒有改變目錄結構。額外的空目錄是否有問題?你有依賴週期嗎? –

+0

事情是這些類不是由文件夾(即客戶端,服務器,util)分隔的。例如,我包含在客戶端jar'a/b'和'z/x/y'中,util包含'q/w/e',並且服務器應該包含所有的休息類,它們可以在'a','z ','z/x','q','q/w'。 – vitalidze

4

最終版本中,我們有同樣的問題在我的公司,即。難以遷移到「良好」項目結構的遺留代碼,以及需要從同一代碼庫構建多個罐子的需求。我們決定定義不同的sourceSets,並使用標準Gradle構建每個sourceSets。

然後,使用迭代器添加JAR-和javadoc任務爲每個sourceSet:

sourceSets.all { SourceSet sourceSet -> 
    Task jarTask = tasks.create("jar" + sourceSet.name, Jar.class) 
    jarTask.from(sourceSet.output) 
    // Configure other jar task properties: group, description, manifest etc 

    Task javadocTask = tasks.create("javadoc" + sourceSet.name, Javadoc.class) 
    javadocTask.setClasspath(sourceSet.output + sourceSet.compileClasspath) 
    javadocTask.setSource(sourceSet.allJava) 
    // Extra config for the javadoc task: group, description etc 

    Task javadocJarTask = tasks.create("javadocJar" + sourceSet.name, Jar.class) 
    javadocJarTask.setClassifier("javadoc") // adds "-javadoc" to the name of the jar 
    javadocJarTask.from(javadocTask.outputs) 
    // Add extra config: group, description, manifest etc 
} 
1

我同意與接受的答案太本金。 我發現一個項目,其中客戶端需要兩個JAR基本上是相同的文件,但Manifest僅通過Class-Path鍵不同。

jar { 
    manifest { 
     attributes(
       "Main-Class": platformMainClass, 
       "Implementation-Title": platformDisplayName, 
       "Implementation-Description": platformDescription, 
       "Platform-Version": platformVersion, 
       "Implementation-Version": version, 
       "Build-Assembly-User": System.getProperty("user.name"), 
       "Build-Assembly-Date": new java.util.Date().toString(), 
       "Class-Path": configurations.compile.collect { "lib/"+it.getName() }.join(' ') 
     ) 
    } 

    duplicatesStrategy = DuplicatesStrategy.EXCLUDE 

    exclude([ 'log4j*.properties', 'uk/gov/acme/secret/product/server/**' ]) 
} 

同樣的清單,然後將源代碼是:

task applicationClientJar(type: Jar, description: "Creates the Application Client JAR file.") { 
    dependsOn compileJava 
    manifest { 
     attributes(
       "Main-Class": platformMainClass, 
       "Implementation-Title": platformDisplayName, 
       "Implementation-Description": platformDescription, 
       "Platform-Version": platformVersion, 
       "Implementation-Version": version, 
       "Assembly-Date": new java.util.Date().toString() 
     ) 
    } 
    archiveName = "acme-client-${platformVersion}.jar" 
    destinationDir = file("${buildDir}/libs") 
    from sourceSets.main.output 

    duplicatesStrategy = DuplicatesStrategy.EXCLUDE 

    exclude([ 'log4j*.properties', 'uk/gov/acme/secret/product/server/**'  } 

所以格熱戈日表示法是正確的,因爲搖籃應該知道有兩種不同的JAR與GAVs。多模塊是首選。

compile "uk.gov.acme.secret:acme:1.0" // CORE 
compile "uk.gov.acme.secret:acme-client:1.0" 

來配置這個問題的唯一方法是使用多模塊式搖籃項目,然後添加一個編譯和/或部署依賴於核心/主項目。

project(':common:acme-micro-service-webapp') { 
    dependencies { 
     compile project(':common:acme-core') 
    } 
} 

在'acme-micro-service-webapp'項目中,這確保首先編譯從屬'common:acme-core'。 PS:我仍在試圖找出更好的解決方案。

PS PS:如果您使用的是Maven,也可以勾選`install'任務。

相關問題