至于现在,我们有一个项目结构,其中包含名为src
的单个源文件夹,其中包含三个模块的源代码。我想做的是:
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.jar
和util.jar
中未包含的所有类。在ant构建脚本中,我们使用difference
ant任务解决了这个问题。如何在gradle中完成(我目前的方法不起作用)?
也许我的做法完全错了。请指教。
P.S。至于现在我们不能改变项目源代码文件夹结构。
答案 0 :(得分:29)
我会在这里发布我的工作解决方案作为答案(我在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
}
}
答案 1 :(得分:22)
我认为这种做法是错误的。我建议制作一个包含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多模块项目,它具有正确的依赖关系,而不仅仅是构建jar的任务。
答案 2 :(得分:4)
我们公司遇到同样的问题,即。难以迁移到“好”项目结构的遗留代码,以及需要从同一代码库构建多个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
}
答案 3 :(得分:2)
我同意校长也同意接受的答案。 我找到了一个项目,其中客户端需要两个基本上属于同一文件的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应该知道GAV有两种不同的JAR。多模块是首选选项。
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&#39;内部项目,这确保了依赖的共同:acme-core&#39;先编译。
PS:我仍在努力寻找更好的解决方案。PS PS:如果你正在使用Maven,也可以挂钩`install&#39;任务。