How to make the gradle ShadowJar task also create sources and javadoc of its children?
Asked Answered
H

2

13

I have a gradle project with 8 child projects and a configured shadowjar task to create an "all" jar. The toplevel project is setup to have dependencies to all its children, this tells shadowjar what to include:

project(':') {
    dependencies {
        compile project(':jfxtras-agenda')
        compile project(':jfxtras-common')
        compile project(':jfxtras-controls')
        compile project(':jfxtras-icalendarfx')
        compile project(':jfxtras-icalendaragenda')
        compile project(':jfxtras-menu')
        compile project(':jfxtras-gauge-linear')
        compile project(':jfxtras-font-roboto')
    }
}

shadowJar {
   classifier = null // do not append "-all", so the generated shadow jar replaces the existing jfxtras-all.jar (instead of generating jfxtras-all-all.jar)
}

This works fine, but maven central is refusing the all jar, because it does not have an associated sources and javadocs jar.

How do I tell gradle to also generate the sources and javadoc? ShadowJar's documentation says it should do this by default.

Hoitytoity answered 27/6, 2017 at 18:43 Comment(3)
Did you find the answer on how to generate and upload a javadoc jar from shadowJar to maven central? I'd like to know too!Lozier
Nope. It's still a thing. Seriously considering switching back to Maven, especially with the Java 9 and Eclipse integration being so buggy still.Hoitytoity
You're only including your local project dependencies in the fat-jar created by the ShadowJar plugin and not external dependencies? If that's the case, I doubt you need ShadowJar at all. You can probably create simple jar tasks, that take to output of the sub-project's compile, source and javaDoc tasks and create a fat-jar yourself.Hanuman
L
6

The shadow plugin doesn't seem to have a feature of building a fat sources/javadocs jars.

Below, I provide a few short tasks (javadocJar and sourcesJar) that will build fat javadoc and source jars. They are linked to be always executed after shadowJar. But it has no dependency on the shadow jar plugin.

subprojects {
    apply plugin: 'java'
}

// Must be BELOW subprojects{}
task alljavadoc(type: Javadoc) {
    source subprojects.collect { it.sourceSets.main.allJava }
    classpath = files(subprojects.collect { it.sourceSets.main.compileClasspath })
    destinationDir = file("${buildDir}/docs/javadoc")
}

task javadocJar(type: Jar, dependsOn: alljavadoc) {
    classifier = 'javadoc'
    from alljavadoc.destinationDir
}

task sourcesJar(type: Jar) {
    classifier = 'sources'
    from subprojects.collect { it.sourceSets.main.allSource }
}

shadowJar.finalizedBy javadocJar
shadowJar.finalizedBy sourcesJar

Note, the subprojects section is required, even if you already apply the java plugin inside your subprojects.

Also note, it doesn't include javadocs of the third party libraries your subprojects might depend on. But usually you wouldn't want to do it anyway, probably.

Langouste answered 24/11, 2017 at 21:52 Comment(8)
I will take a look asap, but real work takes precedenceHoitytoity
Ok, this is pretty close with one caveat: JFXtras uses asciidoclet to generate the javadoc. So thje Javadoc generation fails because the doc was not made to be parsed by the normal javadoc engine. See line 144 github.com/JFXtras/jfxtras/blob/8.0/build.gradleHoitytoity
Show the error message. Also note, in my example the tasks are outside of the subprojects clause. In your file they are inside.Langouste
Probably, it's impossible with asciidoclet. Javadoc supports multiple source locations from which it generates a valid index.html containing all classes and etc, while asciidoclet supports only base path of a specific project.Langouste
Your enhancements were not committed yet, but they are outside of the subprojects (as instructed).The error is simply javadoc parsing the comments and complaining about wrong pointed brackets and not closed html tags. It should not, asciidoc should parse it. But if it is not possible, to spoof maven central (because it requires the javadoc and source to be present next to the jar), I could just generate almost empty jars.Hoitytoity
Even if you tell javadoc stop trying parse asciidoc, as I quickly checked, asciidoc anyway doesn't support specifying multiple source locations to create a single index.html aware of all locations. So therefore it's impossible to create such docs and then pack them in a jar. Another solution would be to publish all your subprojects as individual maven jars with their own javadoc and make the main jar dependent on all of them - when users add the main jar, the rest jars come as transitive dependencies. In this case you would still provide the docs to your users.Langouste
Ok. So the subprojects are published as separate jars, that is how the project is intended. The jars contain JavaFX UI controls, and there is an interactive UI builder tool called SceneBuilder (maintained by Gluon). It can't handle UI controls needing dependency jars, so I also have to publish an all-in-one jar; hence the shadow task. Up until recent this worked fine, until Maven central recently decided to require javadoc and source files for all jars. So now I have to provide something next to the all-in-one jar. Maybe using just one of the subprojects javadoc/source will pass the checks...Hoitytoity
In the meantime, in asciidoclet github make a request for support of multiple source locations so you can provide proper docs in the future at least.Langouste
B
-1

This is an old thread, but I'm posting my solution, as it's a lot easier than the above, and I've confirmed it works:

plugins {
    id 'com.github.johnrengelman.shadow' version '7.1.0'
    id 'signing'
    id 'maven-publish'
}

// If using Spring Boot, this is needed
jar.enabled = true
jar.dependsOn shadowJar

java {
    withJavadocJar()
    withSourcesJar()
}

// Remove the -all extension from the "fat" Jar, or it can't be used
// when published to Maven Central.
shadowJar {
    archiveClassifier.set('')
}

// The contents of this section are described here:
//   https://docs.gradle.org/current/userguide/publishing_maven.html
publishing {
    publications {
        jwtopaLibrary(MavenPublication) {
            artifactId = 'jwt-opa'
            artifacts = [ shadowJar, javadocJar, sourcesJar ]
            pom {
    // etc. ...
}

// Signs the `publication` generated above with the name `jwtopaLibrary`
// Signing plugin, see: https://docs.gradle.org/current/userguide/signing_plugin.html#signing_plugin
signing {
    sign publishing.publications.jwtopaLibrary
}

It's not made clear anywhere, and the information needs to be collected in several places, but for the signing plugin to work, you need the short form hex key ID:

# gradle.properties

# The `signing` plugin documentation is less than helpful; 
# however, this is the magic incantation to find the `keyId`:
#
#   gpg --list-signatures --keyid-format 0xshort
#
# The key also needs to be distributed to public GPG servers:
#
#   gpg --keyserver keyserver.ubuntu.com --send-keys 123...fed
#
# In all cases, we need to use the values from the `pub` key.
signing.keyId=0x1234abcde

Then, it's just a matter of running ./gradlew publish and magic happens (well, not really, you still have to go to Sonatype repository, do the "close & release dance", but you know, whatever).

Britton answered 24/12, 2021 at 23:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.