Background
Project Alice generates Java source code, stores it in sources.jar
, then uploads it to a Maven repository. Project Bob pulls sources.jar
down and needs to use it when compiling. Bob does not know that Alice exists, only where to find sources.jar
.
Versions: JDK 11, Gradle 7.3.1, IntelliJ IDEA 2021.3.1
Problem
Making gradle (and IntelliJ’s IDEA) build using source files embedded in a JAR file. To be clear, the JAR file contents resemble:
$ 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
Attempts
A number of approaches have failed.
sourceSets
Changing sourceSets
doesn’t work:
sourceSets.main.java.srcDirs += "jar:file:${projectDir}/sources.jar!/"
The error is:
Cannot convert URL ‘jar:file:/home/user/dev/project/sources.jar!/’ to a file.
Using a zipTree with sourceSets
doesn’t work, although the error message is telling:
sourceSets.main.java.srcDirs += zipTree(file: "${projectDir}/sources.jar")
Error:
Cannot convert the provided notation to a File or URI.
The following types/formats are supported:
- A URI or URL instance.
This was expected. What was unexpected was that URL instances are allowed, but seemingly not if embedded within a JAR file.
The following allows building Bob, but the IDE is unable to find SourceCode.java
:
sourceSets.main.java.srcDirs += zipTree("${projectDir}/sources.jar").matching {
include "com"
}
build task
Modifying the build task to extract the generated code first partially works:
task codeGen {
copy {
from( zipTree( "sources.jar" ) )
into( "build/gen/java" )
}
sourceSets.main.java.srcDirs += ["build/gen/java"]
}
build { doFirst { codeGen } }
The issue is that removing the build
directory then prevents static compiles (because IDEA cannot find the generated source files). In any case, we don’t want to extract the source files because of all the knock-on problems.
compile task
The following snippet also does not compile:
tasks.withType(JavaCompile) {
source = zipTree(file: "${projectDir}/sources.jar")
}
And not updating sourceSets
ensures that the source files inside the JAR file are not discoverable within the IDE.
Question
How would you instruct Gradle to reference and build source files that are stored in an external Java archive file when compiling a project?