从单个源文件夹中抓取多个jar子

至于现在,我们有一个项目结构,其中包含名为src单个源文件夹,其中包含三个模块的源代码。 我想做的是:

1)编译源代码。 使用sourceSets定义可以轻松完成此操作:

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

2)将编译结果放入三个jar子中。 我通过三个’jar’类型的任务来做这件事:

我现在通过三个单独的任务来做这件事:

  • 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 build脚本中,我们通过使用difference ant任务来解决这个问题。 如何在gradle中完成(我目前的方法不起作用)?

也许我的做法完全错了。 请指教。

PS至于现在我们不能改变项目源代码文件夹结构。

我将在这里发布我的工作解决方案作为答案(我在gradle的论坛上有一个提示)。

gradle中的范围非常奇怪:)我认为每个任务定义都会创建一个“Task”类的对象,在这种特殊情况下类似于“JarTask”。 然后我可以从build.gradle脚本中的任何位置访问该类的任何属性。 但是,我找到了唯一可以看到模式的地方,这些模式包含在jar文件中 – 位于任务的from块中。 所以我现在的工作解决方案是:

1)定义项目级集合以包含要从server.jar排除的模式

2) from serverJar任务块中排除所有模式。

请参阅下面的最终版本

 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 } } 

我认为这种做法是错误的。 我建议制作一个包含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个具有单独类集的jar。 这个解决方案的优点是我们制作了一个具有正确依赖关系的正确Gradle多模块项目,而不仅仅是构建jar的任务。

请阅读多项目构建 。

我们公司遇到同样的问题,即。 难以迁移到“良好”项目结构的遗留代码,以及需要从同一代码库构建多个jar。 我们决定使用标准Gradle定义不同的sourceSets并构建每个sourceSets。

然后我们使用迭代器为每个sourceSet添加jar和javadoc任务:

 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 } 

我也同意接受的答案。 我找到了一个项目,其中客户端需要两个基本上属于同一文件的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/**' } 

所以Grzegorz符号是正确的,因为Gradle应该知道有两种不同的JAR与GAV。 多模块是首选选项。

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

配置此方法的唯一方法是使用Multi-Module Gradle项目,然后将编译和/或部署依赖项添加到核心/主项目。

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

在’acme-micro-service-webapp’项目中,这确保首先编译依赖的’common:acme-core’。

PS:我仍在努力寻找更好的解决方案。

PS PS:如果你正在使用Maven,也可以挂钩`install’任务。