What is executableDir in the Application plugin, and how does it change the location of the start scripts within an install?
answer
- relative script dir, default 'bin'
- moves scripts not lib/
- app home resolved relatively
- offset baked at generation
- match downstream packaging
basics
~20 sexecutableDir is the relative path inside the distribution where the launcher scripts are placed; it defaults to "bin". Setting it (e.g. "runtime/bin") moves the scripts there, while the scripts still resolve the app home relative to their own location.
solid answer
~40 s`executableDir` is an Application-plugin property (mirrored onto the `CreateStartScripts` task) that controls **where, relative to the install root, the start scripts live**. By default it is `"bin"`, giving the familiar `bin/<name>` layout. If you set `application.executableDir = "runtime/bin"`, the launchers end up at `runtime/bin/<name>` inside `build/install/<name>/`, while `lib/` stays at the root. The generated scripts compute the application home relative to their own location, so they keep working even when nested deeper — the script knows how many directories up the install root is. You'd change `executableDir` to match a downstream packaging convention (e.g., an OS package that expects executables under a specific subdirectory, or to coexist with other tooling). It's purely about script placement; it does not move `lib/` or rename anything.
code
kotlin · 6 linesapplication {
mainClass.set("com.acme.Main")
executableDir = "runtime/bin"
}
// build/install/myapp/runtime/bin/myapp
// build/install/myapp/lib/... (lib stays at root)go deeper
Know executableDir defaults to 'bin' and sets where the scripts go.
Explain it's a relative path within the dist, moves only the scripts, and lib/ stays at the root.
Explain why the launcher still works (relative APP_HOME resolution, offset baked at generation) and realistic reasons to change it (downstream packaging layout).
Align executableDir with org-wide container/OS-package conventions so all services share a predictable runtime layout.
## The property `executableDir` is exposed on the `application { }` extension and propagated to the `startScripts` (`CreateStartScripts`) task. It specifies the **relative directory, inside the distribution image, where the launcher scripts are written**. - **Default:** `"bin"` → scripts at `<install>/bin/<name>` and `<install>/bin/<name>.bat`. - **Custom:** e.g. `"runtime/bin"` → scripts at `<install>/runtime/bin/<name>`. ## What it does and doesn't move It only relocates the **scripts**. The `lib/` directory (jars) stays at the install root regardless. So with a custom `executableDir` you get: ``` build/install/myapp/ ├── runtime/ │ └── bin/ │ ├── myapp │ └── myapp.bat └── lib/ └── ...jars... ``` ## Why the app still launches The generated start scripts don't hardcode an absolute path. At runtime they resolve their **own** location and then compute `APP_HOME` by walking up the right number of parent directories. The number of `..` levels is derived from `executableDir` at generation time, so moving the scripts deeper keeps the classpath (which points at `<APP_HOME>/lib`) correct. This is why you must change `executableDir` through the plugin rather than just manually moving the file — Gradle bakes the correct relative offset into the script. ## How to set it ```kotlin application { applicationName = "myapp" mainClass.set("com.acme.Main") executableDir = "runtime/bin" } ``` or on the task directly: ```kotlin tasks.named<CreateStartScripts>("startScripts") { executableDir = "runtime/bin" } ``` ## When you'd use it - Matching an **OS-package or container layout** that expects launchers under a particular path. - Keeping the top of the install clean (e.g., separating runtime entry points from config you add via the distribution CopySpec). - Coexisting with sidecar scripts or wrappers placed elsewhere. ## Caveat Because the offset is baked into the script, **do not** manually move the generated launcher after the fact — set `executableDir` so Gradle computes the correct app-home resolution.
- Does executableDir move the lib/ directory too?No — only the start scripts are relocated; lib/ remains at the install root.
- Why shouldn't you just move the generated script manually instead of setting executableDir?The script bakes in the number of parent directories up to APP_HOME at generation time; set executableDir so Gradle computes the correct relative offset and the lib/ classpath still resolves.
- What is the default value of executableDir?"bin", which yields the conventional bin/<name> location.
saying these in an interview costs you the question
- Thinking executableDir moves or renames lib/ — it only affects where the scripts go.
- Believing you can manually relocate the launcher without changing executableDir — the relative APP_HOME offset would break.