Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

198
Views
Use zipTree como conjunto de fuentes para compilar y compilar estáticamente

Antecedentes

Project Alice genera el código fuente de Java, lo almacena en sources.jar y luego lo carga en un repositorio de Maven. Project Bob extrae sources.jar y necesita usarlo al compilar. Bob no sabe que Alice existe, solo donde encontrar las sources.jar .

Versiones: JDK 11, Gradle 7.3.1, IntelliJ IDEA 2021.3.1

Problema

Hacer que Gradle (y la IDEA de IntelliJ) se construyan utilizando archivos fuente incrustados en un archivo JAR. Para ser claros, el contenido del archivo JAR se parece a:

 $ jar -tvf sources.jar 0 Thu Feb 03 08:38:56 PST 2022 META-INF/ 52 Thu Feb 03 08:38:56 PST 2022 META-INF/MANIFEST.MF 0 Thu Feb 03 08:38:30 PST 2022 com/ 0 Thu Feb 03 08:38:32 PST 2022 com/domain/ 0 Thu Feb 03 08:38:30 PST 2022 com/domain/package/ 938 Thu Feb 03 08:38:32 PST 2022 com/domain/package/SourceCode.java

Las soluciones que extraen los archivos .java del archivo .jar introducen efectos colaterales que nos gustaría evitar, entre ellos:

  • Editable. Los archivos fuente extraídos se pueden editar en el IDE. Nos gustaría que fueran de solo lectura. Podríamos agregar una tarea que configure los archivos como de solo lectura, pero eso se siente como resolver el problema equivocado (complejidad adicional).
  • Sincronización. Cuando se extrae un archivo sources.jar recién generado, tendremos que eliminar el directorio de extracción para eliminar cualquier archivo .java obsoleto que se haya conservado. Si hubiera una manera de evitar la extracción, entonces el acto de extraer el nuevo archivo sources.jar garantizaría la corrección (sin complejidad adicional). Al desarchivar los archivos .java, es posible ingresar a un estado inconsistente:
 $ jar -tvf sources.jar | grep java$ | wc -l 61 $ find src/gen -name "*java" | wc -l 65

Si hubiera una forma de tratar las fuentes. sources.jar como un directorio de origen sin extraer los archivos, estos efectos colaterales desaparecerían.

intentos

Varios enfoques han fallado.

conjuntos de fuentes

Cambiar sourceSets no funciona:

 sourceSets.main.java.srcDirs += "jar:${projectDir}/sources.jar!/"

el error es:

No se puede convertir la URL 'jar:/home/user/dev/project/sources.jar!/' a un archivo.

El uso de zipTree con sourceSets no funciona, aunque el mensaje de error dice:

 sourceSets.main.java.srcDirs += zipTree(file: "${projectDir}/sources.jar")

Error:

No se puede convertir la notación proporcionada en un archivo o URI.

Se admiten los siguientes tipos/formatos:

  • Una instancia de URI o URL.

Esto era de esperar. Lo inesperado fue que las instancias de URL están permitidas, pero aparentemente no si están incrustadas en un archivo JAR.

Lo siguiente permite construir a Bob, pero el IDE no puede encontrar SourceCode.java :

 sourceSets.main.java.srcDirs += zipTree("${projectDir}/sources.jar").matching { include "com" }

construir tarea

La modificación de la tarea de compilación para extraer primero el código generado funciona parcialmente:

 task codeGen { copy { from( zipTree( "${projectDir}/sources.jar" ) ) into( "${buildDir}/src/gen/java" ) } sourceSets.main.java.srcDirs += ["${buildDir}/src/gen/java"] } build { doFirst { codeGen } }

El problema es que eliminar el directorio de build evita las compilaciones estáticas (porque IDEA no puede encontrar los archivos fuente generados). En cualquier caso, no queremos extraer los archivos de origen debido a todos los problemas colaterales.

compilar tarea

El siguiente fragmento tampoco se compila:

 tasks.withType(JavaCompile) { source = zipTree(file: "${projectDir}/sources.jar") }

No actualizar sourceSets significa que el IDE no puede descubrir los archivos fuente.

tarea de sincronización

En su lugar, podríamos extraer los archivos en el directorio de origen principal, como:

 def syncTask = task sync(type: Sync) { from zipTree("${projectDir}/sources.jar") into "${projectDir}/src/gen/java" preserve { include 'com/**' exclude 'META-INF/**' } } sourceSets.main.java.srcDir(syncTask)

Si bien eso soluciona el problema de la limpieza, nos quedan los problemas originales que nos gustaría evitar.

Raíz de contenido

Establecer la raíz del contenido y marcar la carpeta de origen desde IntelliJ IDEA funciona. El IDE actualiza .idea/misc.xml para incluir:

 <component name="FrameworkDetectionExcludesConfiguration"> <file type="web" url="file://$PROJECT_DIR$" /> <file type="web" url="jar://$PROJECT_DIR$/project/sources.jar!/" /> </component>

En teoría, el complemento de idea puede tener la capacidad de establecer este valor.

Pregunta

¿Cómo le indicaría a Gradle que haga referencia y construya usando archivos de origen que se almacenan en un archivo de Java externo al compilar un proyecto ( sin extraer el archivo) de modo que IDEA también pueda resolver estáticamente los archivos de origen?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Decidimos que extraer el archivo jar sería el mejor enfoque después de todo:

 apply plugin: 'idea' final GENERATED_JAR = "${projectDir}/sources.jar" final GENERATED_DIR = "${buildDir}/generated/sources" task extractSources(type: Sync) { from zipTree(GENERATED_JAR) into GENERATED_DIR } sourceSets.main.java.srcDir extractSources clean.finalizedBy extractSources idea.module.generatedSourceDirs += file(GENERATED_DIR)

Esta:

  • Conserva las fuentes generadas después de la clean .
  • Emite una advertencia en el IDE al modificar las fuentes generadas
  • Combina el proceso de compilación con la extracción de archivos fuente
  • Reutiliza la ruta de build/generated/sources
  • Mantiene el archivo .jar y los archivos .java sincronizados

En efecto, los siguientes comportamientos funcionan como se esperaba:

  • ./gradlew clean : deja intactos los archivos .java extraídos, efectivamente
  • ./gradlew build -- vuelve a sincronizar archivos .java con contenidos .jar
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!