How to force a final archiving task for creation of an artifact


(Derek Ealy) #1

Hi, I’m still pretty new to Gradle, and have been having some trouble with artifacts. I have a multi-project build with about 33 sub-projects. Some of these projects have to create their own archive files after the assemble has finished. For some reason I haven’t been able to consistently get this to work. Sometimes one or two projects don’t produce the extra jar file and I’m assuming that they are running my jar task before the compile task has completed (since I get no errors).

Maybe I’m just misunderstanding the proper way to do this in Gradle. Here is an example from one of these projects:

task createClassesJar(type: Jar) {
description = 'Assembles and builds classes and produces jar'
archiveName = intermediateClassesJar
destinationDir = file(intermediateClassesDir)
from fileTree(dir: 'build/intermediates/classes/release', include: '**/*.class')
}

assemble.dependsOn createClassesJar

artifacts {
    archives file("$intermediateClassesDir/$intermediateClassesJar")
}

If I run grade assemble from the master project sometimes this intermediate jar file isn’t created.

What is the proper way to tell Gradle that I want to execute always execute this task after it has already generated the needed class files?

Thanks, Derek


(Sterling Greene) #2

What’s producing the class files? If it’s a JavaCompile task, you should be able to do:

task createClassesJar(type: Jar) {
  // other stuff above from() in original code
  from(nameOfTheCompileTask)
}

The ArtifactHandler understands that archives that come from particular tasks require dependencies, so if you just use the task name it’ll translate that into a file + dependency:

artifacts {
   archives createClassesJar
}

I think that also makes assemble depend on the task that creates the jar too.

This might help: https://gradle.org/feature-spotlight-incremental-builds/


(Derek Ealy) #3

It would be great if I could get that to work. I didn’t quite realize that you should be able to specify tasks to the from property of the Jar obj, or to the archives property.

However right now when I say from(JavaCompile) in the jar task I get and error:
Cannot convert the provided notation to a File or URI: class org.gradle.api.tasks.compile.JavaCompile.
The following types/formats are supported:

  • A String or CharSequence path, e.g ‘src/main/java’ or ‘/usr/include’
  • A String or CharSequence URI, e.g ‘file:/usr/include’
  • A File instance.
  • A URI or URL instance.

(Mark Vieira) #4

The name of the task is lowercase, javaCompile.


(Derek Ealy) #5

It still doesn’t like it. Gradle says that javaCompile is not a property of the createClassesJar task. I’ve seen this error a lot over the past few days. Here is the current task definition:

task createClassesJar(type: Jar) {
archiveName = intermediateClassesJar
destinationDir = file(intermediateClassesDir)
from (javaCompile)}

(Mark Vieira) #6

My typo, the name of the task is compileJava.


(Derek Ealy) #7

same error

A problem occurred evaluating project ‘:VulcanRadio’.

Could not find property ‘compileJava’ on task ‘:VulcanRadio:createClassesJar’.


(Mark Vieira) #8

Are you using the ‘java’ plugin? What task is responsible for compiling these classes?


(Derek Ealy) #9

Using the com.android.application plugin. Ok, I guess using this plugin removes the compileJava task? There is a compileReleaseJava task listed, however if I use that in the from property I still get the error message about compileReleaseJava not being a valid property


(Mark Vieira) #10

Ah, that’s the culprit. Because Android projects can have multiple variants, there are multiple compile tasks (at least two, debug and release). You’ll want to additionally create a JAR task for each of these.

android.applicationVariants.all { variant ->
    task "${variant.name}ClassesJar"(type: Jar) {
        classifier = variant.name
        destinationDir = file("$buildDir/libs/$variant.dirName")
        from variant.javaCompile
    }
}

(Derek Ealy) #11

Hey Mark thanks for all the help yesterday. I’m still not able to get the whole thing to run. how do I get the archives to refer to the tasks created in the applicationVariants loop?

If I use this

artifacts {
   archives debugClassesJar
}

I once again get the error message about not finding the property debugClassesJar


(Derek Ealy) #12

If I put the archives step inside of a loop like this:

artifacts {
    android.applicationVariants.all { variant ->
        archives "${variant.name}ClassesJar"
    }
}

It goes further, but still isn’t happy, returns an error about not being able to convert the provided notation to an object of type PublishArtifact: debugClassesJar.


(Mark Vieira) #13

You’ll probably have to put this inside the closure where you are creating the task.

android.applicationVariants.all { variant ->
    task "${variant.name}ClassesJar"(type: Jar) {
        classifier = variant.name
        destinationDir = file("$buildDir/libs/$variant.dirName")
        from variant.javaCompile
    }
    artifacts {
        archives tasks."${variant.name}ClassesJar"
    }
}

(Hara Kang) #14

You saved my day :slight_smile: