How to use minimize() from shadowJar properly? - gradle

In my configuration I have:
shadowJar {
minimize()
archiveName = "fat.jar"
}
When I do fatjar, shadowJar doesn't includes my code from package mystdeim
I found in documentation that I can force to exclude some dependencies from minimize by exclude(dependency('io.*:.*:.*')), but how to exclude my code from minimize task?

Related

Gradle, shadowJar: use relocate inside task

I have the following task:
task myJar(type: Jar) {
archiveName = 'myJar.jar'
includeEmptyDirs = false
destinationDir = rootProject.libsDir
dependsOn compileJava
manifest.attributes('Class-Path': '../lib/commons-lang-2.5.jar')
into '/', {
from compileJava.destinationDir
include 'com/myCompany/project/util/order/**',
'com/myCompany/project/event/**',
}
}
and I would like to relocate all classes from com/myCompany/project/event/** to com/myCompany/relocated/project/event/** (so that some apps using my jar and having com.myCompany.project.event package defined will avoid any possible conflicts)
I discovered that it can be done using shadow plugin and I tried to add
relocate 'com.myCompany.project.event.', 'com.myCompany.relocated.project.event.'
under this task but it doesn't seem to work.
Does anybody know where I should add this line?
You can achieve this by adding below plugin to your build.gradle
apply plugin: 'com.github.johnrengelman.shadow'
After adding this plugin add below code to your build.gradle file
shadowJar {
relocate 'com.myCompany.project.event', 'com.myCompany.relocated.project.event'
}
After adding this, to ensure your ShadowJar task runs before build, add this line at the end
assemble.dependsOn shadowJar
This will ensure that shadow jar task is triggered before assemble/build task during gradle build.
On doing the Gradle build, you should see all your packages and their corresponding dependencies relocated from 'com.myCompany.project.event' to 'com.myCompany.relocated.project.event'.
For more info you can refer to ShadowJarUserGuide

Gradle ShadowJar output contains obfuscated and non-obfuscated classes

in my simple gradle build I would like to use ShadowJar and ProGuard together. I have found examples where the output of the shadowJar task is the input of the proguard one, which works fine, however in my case I would prefer first creating the small obfuscated jar first where I nicely specify the library dependencies and get proguard to focus only on my code and then I would like to pass that to the shadowjar plugin for fatjar packaging.
My setup is the following:
task obfuscate(type: proguard.gradle.ProGuardTask) {
injars jar
outjars "build/libs/foo-${project.version}-pg.jar"
...
}
shadowJar {
from obfuscate
configurations = [project.configurations.embed]
}
shadowJar.dependsOn obfuscate
And my problem is that the shadowJar output contains all the libraries unobfuscated (fine), my obfuscated code (fine) and my unobfuscated code. So somehow the original classes sneak in and I am not seeing how is that happening. I am not able to specify to shadowJar to package the dependencies and the proguard output jar together.
Do you see where is the problem in my approach?
Try this, works for me:
task shadowJar2( type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar ) {
baseName = jar.baseName
from obfuscate
configurations = [project.configurations.embed]
classifier = 'shadow'
//version =
}
The problem is that the default shadowJar task takes your 'main' sourceset in addition to the obfuscated + library jars. By defining your own custom 'shadowJar2' task, you are explicitly defining your sources, which in this case is only jars ('obfuscate' + 'embed') and not a sourceset.

Sequencing dependencies of multiple Gradle plugin tasks

Please note: Although I specifically mention two Gradle plugins here, this is 100% a question about understanding task dependencies in Gradle, and does not require any knowledge of the individual plugins (I think)!
I have a project that will use two Gradle plugins:
The Gradle Shadow plugin, which will produce a self-contained "fat jar" (basically a large jar with all my classes plus the classes of all my transitive dependencies, which then allows me to just run java -jar myapp.jar without having to manage the jar's external classpath, etc.). This will produce a fat jar at build/libs/myapp.jar; and
The Gradle Launch4J plugin, which uses Launch4J under the hood to convert a jar into a native executable (EXE, etc.). Obviously the fat jar has to be created prior to the Launch4J tasks run, otherwise they'll have nothing to wrap inside of an EXE!
Here's my build.gradle:
import com.github.jengelman.gradle.plugins.shadow.transformers.ServiceFileTransformer
plugins {
id 'groovy'
id 'application'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '1.2.3'
id 'edu.sc.seis.launch4j' version '2.3.0'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
group = 'hotmeatballsoup'
mainClassName = 'com.me.myapp.Driver'
repositories {
mavenCentral()
jcenter()
}
dependencies {
compile(
'org.codehaus.groovy:groovy-all:2.4.7'
,'org.slf4j:slf4j-api:1.7.24'
,'org.slf4j:slf4j-simple:1.7.24'
)
}
manifest {
attributes 'Main-Class': mainClassName
}
jar {
manifest {
attributes 'Main-Class': mainClassName
}
baseName = 'zimbus'
}
shadowJar {
transform(ServiceFileTransformer) {
exclude 'META-INF/*.DSA'
exclude 'META-INF/*.RSA'
exclude 'LICENSE*'
}
transform(com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer) {
resource = 'reference.conf'
}
classifier = ''
}
publishing {
publications {
shadow(MavenPublication) {
from components.shadow
artifactId = 'zimbus'
}
}
}
launch4j {
outfile = 'zimbus.exe'
mainClassName = 'com.me.myapp.Driver'
icon = 'zimbus.ico'
jar = 'build/libs/gradle-launch4j-example.jar'
}
At the command-line I run:
./gradlew clean build shadowJar createAllExecutables
The intention here is that I want the fat jar created first (invoked when shadowJar runs) and then for Launch4J to kick in (which is invoked when createAllExecutables runs). But when I run this I get the following exception:
:createExe FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':createExe'.
> Launch4J finished with non-zero exit value 1
launch4j: Application jar doesn't exist.
I'm pretty sure the createAllExecutables task is firing before the shadowJar task, and thus having nothing (no fat jar) to bundle up inside an EXE.
Can someone confirm my suspicion and help me define the dependsOn declaration that will order my tasks correctly? Or if the tasks are executing in the correct order, maybe offer any ideas as to what is causing the error?
Once you write
createAllExecutables.dependsOn shadowJar
you'll define the dependency between createAllExecutables task and shadowJar, which means every time Gradle decide to invoke createAllExecutables (e.g. because you pass that to the command line, or other task will depend on it) shadowJar will also be added to the task graph. So in that case when you invoke gradle createAllExecutables the shadowJar will be also executed.
But you can also write
createAllExecutables.mustRunAfter shadowJar
In that case, you won't introduce any dependency relation between tasks, but you will instrument Gradle about anticipated order for those two tasks. In that case, once you invoke gradle createAllExecutables the shadowJar won't be executed.
I think the dependsOn relation is more applicable in your case, since in order to create executables you need to have fat jar already, so it's a depend on relation, not must run after.

How to simplify this Gradle command line?

I am new to Gradle and have gotten a fairly sophisticated build working with it so far (runs tests, uses CodeNarc, generates API docs, generates a sources JAR, etc.). The command line for a "full build" (that is, to execute all the major tasks that the CI server should be running), I need to enter the following Gradle command at the shell:
gradle clean build check groovydoc sourcesJar createPom dist -Pversion=<version>
Where <version> is the version I want to build.
I would like to condense this and add an alias so that all of the above can be accomplished with something simple, like:
gradle full-build
Is this possible? If so, how?
My build.gradle
apply plugin: 'groovy'
apply plugin: 'maven'
apply plugin: 'codenarc'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.3'
testCompile 'junit:junit:4.11'
}
groovydoc
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
artifacts {
archives sourcesJar
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
task dist(type: Zip, dependsOn: build) {
classifier = 'buildreport'
from('build/test-results') {
include '*.xml'
into 'tests'
}
from('build/reports/codenarc') {
into 'reports'
}
from('build/docs') {
into 'api'
}
from(sourcesJar) {
into 'source'
}
from('build/libs') {
exclude '*-sources.jar'
into 'bin'
}
}
task createPom << {
pom {
project {
groupId "me"
artifactId "myapp"
version version
}
}.writeTo("build/libs/myapp-${version}.pom")
}
In the above build invocation, at least check and sourcesJar can be omitted already. (build depends on check, and from(sourcesJar) tells Gradle that dist depends on sourcesJar.) By adding further task dependencies (e.g. build.dependsOn dist), you can cut it down to gradle clean build -Pversion=.... dist should not depend on build but on the specific tasks that produce the artifacts that go into the zip (e.g. groovydoc and createPom).
Reducing gradle clean build to gradle fullBuild is more difficult, as Gradle doesn't currently have a first-class concept of "aliases", and adding build.dependsOn(clean) is usually not desirable. One way out is to implement your own aliasing mechanism by manipulating gradle.startParameter.taskNames.

Gradle : Generating sources from WSDL & XSD and adding it to main classpath for compilation

I am failry new to gradle and have a multiproject gradle build to which want to add a WSDL2Java related tasks to one of the project.
I have coded the necessary tasks to generate,compile,package the generated stubs into a jar and add it to the classpath.
Now , i want to perform these tasks before the java compilation is started.
Below is how i coded the new tasks
task genClasses(type: JavaExec) {
//Run WSDL2Java and generate java source files.
}
task compileClasses(dependsOn:'genClasses'){
//Use ant.javac or add type:JavaCompile in task defination as shown below
// task compileClasses(dependsOn:'genClasses',type:JavaCompile)
}
task packageClasses(dependsOn:'compileClasses',type:Jar){
//package my jar
}
task createStubs(dependsOn: 'packageClasses'){
//add created jar to the classpath
}
compileJava.dependsOn createStubs
The build fails with exception and shows below message
Circular dependency between tasks. Cycle includes [task ':projectx:genWsdlClasses', task ':projectx:classes'].
I figured out that the compileClasses tasks somehow is causing this circular dependency, but not sure how to get rid of it?
Are there any other better or idiomatic ways to perform this source generation, compilation of generated source,packaging and adding it to the main sourceset classpath before the main source gets build?
I use the Jaxb-Plugin available here. My Gradle build file looks like this:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'no.entitas.gradle.jaxb:gradle-jaxb-plugin:2.0'
}
}
dependencies {
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.5-1'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.5-1'
}
generateSchemaSource.destinationPackage = "my.custom.package"
I believe that this will create the jaxb classes that you want. Does that help?
Use the plugin "no.nils.wsdl2java"
https://plugins.gradle.org/plugin/no.nils.wsdl2java
The plugin takes care of hooking it in to the build and clean tasks.

Resources