How can I run a console command in Gradle upon build?

Viewed 280

I'm currently working on a project that has a native component in Rust and a Java component. The main build system is Gradle, and I want Gradle to invoke the Rust build system (Cargo) upon build, every time, to ensure that the proper shared libraries exist for JNI to take place, and for those libraries to be recompiled as needed. After research, I came up with this:

task buildRustDebug(type:Exec){
    workingDir './native'
    commandLine 'cargo', 'build'
}

task buildRustRelease(type:Exec){
    workingDir './native'
    commandLine 'cargo', 'build', '--release'
}

task buildRust(){
    dependsOn 'buildRustDebug'
    dependsOn 'buildRustRelease'
}

build dependsOn 'buildRust'

This all works fine, except for the last line that establishes a dependency with the build task. This line, when present, gives the following error when I attempt to run any task:

Build file '<censored>' line: 23

A problem occurred evaluating root project '<censored>'.
> Could not get unknown property 'dependsOn' for root project '<censored>' of type org.gradle.api.Project.

It looks like somehow the build task doesn't exist until after the code in my main file runs. How can I accomplish what I want? Note that this code is in the root project of a multi-project Gradle build.

1 Answers

The comment you got on the question is correct. But just to give you some context (and make it possible to mark the question as solved):

Gradle uses either Groovy or Kotlin for the scripting language. You are using Groovy.

When you write dependsOn 'buildRustDebug', you are calling a method called dependsOn with the String argument 'buildRustDebug'. This works because in Groovy, method parenthesis are optional. So it is the same as dependsOn('buildRustDebug').

When you write build dependsOn 'buildRust', it is syntactically incorrect. You want to call the dependsOn method on the build object with an argument. Try this instead:

build.dependsOn 'buildRust' // Or
build.dependsOn('buildRust')

Notice the dot before the method call.

Another thing is that build is one of the "outermost" tasks in the dependency trees, and it itself depends on other tasks like compileJava and test. If you want to make sure your Rust project is built and available before assembling your application or testing it, you probably need to move the dependency down the tree a bit. Otherwise you risk that the buildRust task is the very last thing it does, whereas it should probably be one of the first things it does.

Related