java - published - gradle tutorial
Gradle mĂșltiples tarros de una sola carpeta de origen (4)
Creo que el enfoque está mal. Recomiendo hacer un proyecto con 3 sub proyectos.
project
- util
- server (depends on util)
- client (depends on util)
Si por alguna razón no puede cambiar la estructura de la clase, use este tipo de archivos de compilación:
settings.gradle
include ''util'', ''client'', ''server''
construir.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'')
}
}
Aún necesita directorios para subproyectos, pero las fuentes están en un lugar como usted quería.
Cuando gradle assemble
, tendrás 3 frascos con un conjunto separado de clases. La ventaja de esta solución es que realizamos un proyecto de varios módulos Gradle adecuado con las dependencias correctas, no solo las tareas para construir tarros.
Por favor, lea Multi-Project Builds .
Por ahora, tenemos una estructura de proyecto con una sola carpeta de origen llamada src
, que contiene el código fuente de tres módulos. Lo que quiero hacer es:
1) Compilar el código fuente. Esto se hace fácilmente con la definición de sourceSets:
sourceSets {
main {
java {
srcDir ''src''
}
}
}
2) Poner los resultados de la compilación en tres frascos. Estoy haciendo esto a través de tres tareas de tipo ''jar'':
Estoy haciendo esto ahora a través de tres tareas separadas:
util.jar
task utilJar(type: Jar) { from(sourceSets.main.output) { include "my/util/package/**" } }
cliente.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) }
La cosa es que server.jar
debe contener todas las clases que no están contenidas en client.jar
y util.jar
. En el script de compilación de ant, resolvemos este problema utilizando la tarea difference
ant. ¿Cómo se puede hacer esto en gradle (mi enfoque actual no funciona)?
Tal vez mi enfoque es completamente erróneo. Por favor aconséjame.
PS como ahora NO PODEMOS cambiar la estructura de carpetas del código fuente del proyecto.
Estoy de acuerdo en principio con la respuesta aceptada también. Encontré un proyecto donde el cliente requiere dos JAR esencialmente del mismo archivo, excepto que el Manifiesto es diferente solo por la clave 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/**'' ])
}
El mismo manifiesto y el código fuente entonces es:
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/**'' }
Así que la notación de Grzegorz es correcta, porque Gradle debe saber que hay dos JAR diferentes con GAV. Multi-módulo es la opción preferida.
compile "uk.gov.acme.secret:acme:1.0" // CORE
compile "uk.gov.acme.secret:acme-client:1.0"
La única forma de configurar esto es usar el proyecto Gradle de varios módulos y luego agregar una compilación y / o implementar una dependencia al proyecto principal / principal.
project('':common:acme-micro-service-webapp'') {
dependencies {
compile project('':common:acme-core'')
}
}
Dentro del proyecto ''acme-micro-service-webapp'', esto asegura que el ''common'' dependiente: acme-core se compile primero.
PD: todavía estoy tratando de encontrar una mejor solución.
PS PS: Si está utilizando Maven y puede ser posible enganchar en la tarea `instalar ''.
Publicaré mi solución de trabajo aquí como respuesta (tengo una pista en el foro de gradle).
Los ámbitos en gradle son una cosa muy extraña :) Pensé que cada definición de tarea crea un objeto de alguna clase de ''Tarea'', que es algo así como ''JarTask'' en este caso particular. Luego puedo acceder a cualquier propiedad de la clase desde cualquier lugar en mi script build.gradle. Sin embargo, encontré el único lugar donde puedo ver los patrones, que están incluidos en el archivo jar, dentro de un bloque de una tarea. Así que mi solución de trabajo por ahora es:
1) Defina una colección a nivel de proyecto para contener patrones que se excluirán de server.jar
2) Excluir todos los patrones from
bloque de la tarea serverJar
.
Por favor, vea la versión final a continuación.
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
}
}
Tenemos el mismo problema en mi empresa, es decir. Código heredado que es difícil de migrar a una estructura de proyecto "buena", y la necesidad de construir varios archivos jar desde la misma base de código. Decidimos definir diferentes SourceSets y construir cada uno de los SourceSets usando Gradle estándar.
Luego usamos iteradores para agregar tareas jar y javadoc para cada conjunto de fuente:
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
}