Customize place of start scripts in gradle build

Viewed 1277

I'm new to gradle any trying to package a little project of mine. When building my distribution package, the structure is as follows:

my-project.zip
|
+- my-project
   |
   +- bin (containing start scripts)
   +- lib
   +- xyz (folders from src/dist)

What I want to achieve is having the start scripts in the project root folder instead of the bin subfolder (I know that this is some kind of convention, but I also like to start my application from within the application folder):

my-project.zip
|
+- my-project
   |
   +- lib
   +- xyz (folders from src/dist)
   +- my-project.bat
   +- my-project.sh

Is this possible?

I've tried setting tasks.startScripts.outputDir but with no success (scripts were completely removed from the distribution package).

Update

In addition to lu.koerfer's answer I had to modify the start scripts to take into account the changed APP_HOME:

startScripts {
    startScripts.applicationName = artefactsBaseName
    doLast {
        def windowsScriptFile = file getWindowsScript()
        def unixScriptFile = file getUnixScript()
        windowsScriptFile.text = windowsScriptFile.text.replace('set APP_HOME=%DIRNAME%..', 'set APP_HOME=%DIRNAME%')
        unixScriptFile.text = unixScriptFile.text.replace('cd "`dirname \"$PRG\"`/.." >/dev/null', 'cd "`dirname \"$PRG\"`" >/dev/null')
    }
}
1 Answers

You don't want to care about the creation of the start scripts (the startScripts task), but about the creation of the zip file (the distZip task) to control where the files will be put. For this purpose, you could directly use the distZip task or the DistributionContainer from the Gradle Distribution plugin, which is automatically applied with the Gradle Application plugin. The DistributionContainer allows you to manage the creation of multiple distributions in your Gradle project and the Application plugin uses the main distribution by default.

distributions.main {
    contents {
        from startScripts
    }
}

This piece of code simply adds the outputs of the startScripts tasks to the main distribution contents. They will be placed in the root folder of this distribution, since you did not specify a child CopySpec with an into method.

I assume that you want your start scripts only in the root folder, but not in the bin folder as well. Since you can only exclude files of a Copy task based on their source path and not on their destination path, you'll need to exclude them when they are copied, via the eachFile method (because then their destination is known):

distZip {
    eachFile { file ->
        if (file.path.contains('bin')) {
            file.exclude()
        }
    }
}

Of course, this piece of code will remove the whole bin directory from the zip file, so you could need to redescribe the condition in the closure for other use cases.

Related