Search code examples
gradlegradle-kotlin-dsl

Is there really no way to set the working directory for "gradle run"?


When I do "gradle run", I'd like for the java command to be executed in my $projectDir/dist folder instad of project dir. This is where my application is getting built, it wouldn't make sense for it to run from the projectDir directly. From my research I keep seeing that this is somehow impossible? Is that really true? I've tried the following:

application() {
    mainClass.set("com.myapp.MainClass")
    applicationDefaultJvmArgs = listOf("-Duser.dir=$buildDir\\dist")
}

But that did not change the working directory. I can create another task:

tasks.register<JavaExec>("runApp") {
    classpath = sourceSets["main"].runtimeClasspath
    mainClass.set("com.myapp.MainClass")
    workingDir = file("$buildDir\\dist")
}

In which I can set the working directory, but it seems silly not to use the standard tasks that come with gradle. Any advice?


Solution

  • Any existing task can be modified, so long as you know its name. Knowing the type is also important (when using Groovy it is not critical, but can be very useful). So lets find out about the run task.

    The Gradle Application plugin automatically creates a task called run. run has the type JavaExec, which has a property, workingDir, that defaults to the project directory.

    Given this, we can now modify the existing run task in Groovy:

    // build.gradle
    plugins {
      application
    }
    
    tasks.named('run') {
      workingDir = file("$buildDir/dist")
    }
    

    Or in Kotlin

    // build.gradle.kts
    plugins {
      application
    }
    
    tasks.named<JavaExec>("run") {
      workingDir = file("$buildDir/dist")
    }
    

    Note that the Kotlin type-safe accessor for the run task clashes with the run {} scope function, and so .configure {} is required:

    tasks.run {
      // doesn't configure the `run` task, because `run {}` is a scope function
    }
    
    // using .configure {} is required to configure the 'run' task:
    tasks.run.configure {
      workingDir = file("$buildDir/dist")
    }
    

    See also

    I also found these answers, but they are older and contain some outdated syntax, so I thought it was worth revisiting this question.