Search code examples
androidgradleandroid-gradle-plugingradle-plugingradle-kotlin-dsl

How to save output from exec (running a bash script) to a variable in a gradle plugin


I am implementing a Gradle Plugin in kotlin in an Android project. The goal of the Plugin is to run a bash script and do something with the result. I've managed to get the script to run but I can't figure out how to save the output from the script to a variable.

I have a working gradle task that does what I am trying to achieve in the plugin:

task myTask(type: Exec) {
    executable 'sh'
    commandLine "./my-script.sh", "."
    standardOutput = new ByteArrayOutputStream()
    doLast {
        def res = standardOutput.toString().split(',')
        println "Output: ${res[0]}"
        println "Output1: ${res[1]}"
        println "Output2: ${res[2]}"
        println "Output3: ${res[3]}"
        println "Output4: ${res[4]}"
    }
}

My plugin that just runs my script without storing the result in a variable looks like this:

class MyGradlePlugin : Plugin<Project> {
    override fun apply(project: Project) = project.run {
        project.afterEvaluate {
            exec {
                executable("sh")
                commandLine("./my-script.sh", ".")
            }
        }
    }
}

What I've tried

I've tried adding standardOutput since that's what makes it work for the task:

class MyGradlePlugin : Plugin<Project> {
    override fun apply(project: Project) = project.run {
        project.afterEvaluate {
            val stdout = ByteArrayOutputStream()

            exec {
                executable("sh")
                commandLine("./my-script.sh", ".")
                standardOutput = stdout
            }
        }
    }
}

However, this doesn't work and Android Studio gives this error: Cannot access class 'java.io.OutputStream'. Check your module classpath for missing or conflicting dependencies

Even if it did work I also don't know how I would save the result in a variable like I did in the task. Doing this does not work since res gets set to an ExecResult:

class MyGradlePlugin : Plugin<Project> {
    override fun apply(project: Project) = project.run {
        project.afterEvaluate {
            val stdout = ByteArrayOutputStream()

            val res = exec {
                executable("sh")
                commandLine("./my-script.sh", ".")
                standardOutput = stdout
            }
        }
    }
}

Do you have any idea what I am doing wrong? Any help is greatly appreciated. Thank you!


Solution

  • Thanks to @romtsn's comment I managed to find a very simple solution.

    class MyGradlePlugin : Plugin<Project> {
        override fun apply(project: Project) = project.run {
            project.afterEvaluate {
                val stdout = ByteArrayOutputStream()
    
                val res = exec {
                    executable("sh")
                    commandLine("./my-script.sh", ".")
                    standardOutput = stdout
                }
    
                val res = stdout.toString().split(',')
                println "Output: ${res[0]}"
                println "Output1: ${res[1]}"
                println "Output2: ${res[2]}"
                println "Output3: ${res[3]}"
                println "Output4: ${res[4]}"
            }
        }
    }
    

    Android Studio is still giving me the OutputStream error but it works nevertheless. I am suspecting it is an issue with Android Studio. Invalidating caches and restarting did not make it go away.