This guide explains how to build JPhotoTagger distribution packages for Linux, Windows, and macOS.
The Gradle wrapper will automatically download the correct Gradle version.
You can only build packages for your current operating system. Cross-compilation is not supported by jpackage.
./gradlew jpackage
Output: build/jpackage/JPhotoTagger/
gradlew.bat jpackage
Output: build\jpackage\JPhotoTagger\
./gradlew jpackage
Output: build/jpackage/JPhotoTagger.app/
To build with a specific version number:
./gradlew jpackage -Pversion=2.0.0
./build/jpackage/JPhotoTagger/bin/JPhotoTagger
build\jpackage\JPhotoTagger\JPhotoTagger.exe
Or double-click JPhotoTagger.exe in File Explorer.
open build/jpackage/JPhotoTagger.app
Or double-click JPhotoTagger.app in Finder.
Releases are built automatically using GitHub Actions.
Tag the commit with a version:
git tag v2.0.0
git push origin v2.0.0
GitHub Actions will:
Test builds are marked as pre-release and have dev-YYYYMMDD-HHMMSS version format.
Create a packaging/ directory in the project root with platform-specific icons:
| Platform | File | Format | Recommended Size |
|---|---|---|---|
| Linux | JPhotoTagger.png |
PNG | 256x256 or larger |
| Windows | JPhotoTagger.ico |
ICO | Multi-resolution (16-256px) |
| macOS | JPhotoTagger.icns |
ICNS | Multi-resolution |
The build will automatically detect and use these icons.
Creating icons:
PNG to ICO (Windows): Use ImageMagick:
convert icon-256.png -define icon:auto-resize=256,128,64,48,32,16 JPhotoTagger.ico
PNG to ICNS (macOS): Use iconutil on macOS:
mkdir JPhotoTagger.iconset
sips -z 16 16 icon.png --out JPhotoTagger.iconset/icon_16x16.png
sips -z 32 32 icon.png --out JPhotoTagger.iconset/icon_16x16@2x.png
sips -z 32 32 icon.png --out JPhotoTagger.iconset/icon_32x32.png
sips -z 64 64 icon.png --out JPhotoTagger.iconset/icon_32x32@2x.png
sips -z 128 128 icon.png --out JPhotoTagger.iconset/icon_128x128.png
sips -z 256 256 icon.png --out JPhotoTagger.iconset/icon_128x128@2x.png
sips -z 256 256 icon.png --out JPhotoTagger.iconset/icon_256x256.png
sips -z 512 512 icon.png --out JPhotoTagger.iconset/icon_256x256@2x.png
sips -z 512 512 icon.png --out JPhotoTagger.iconset/icon_512x512.png
sips -z 1024 1024 icon.png --out JPhotoTagger.iconset/icon_512x512@2x.png
iconutil -c icns JPhotoTagger.iconset
To include additional files (manual, scripts, etc.) in the app-image:
Create a resources directory for jpackage:
mkdir -p packaging/resources
Add files to bundle:
cp dist_files/manual/Manual_de.pdf packaging/resources/
cp -r dist_files/scripts packaging/resources/
Modify build.gradle.kts jpackage task to add:
"--resource-dir", resourceDir.resolve("resources").absolutePath
By default, the build creates portable app-images. To create native installers instead:
| Platform | Installer Type | Required Tools |
|---|---|---|
| Linux | .deb |
dpkg-deb (installed by default on Debian/Ubuntu) |
| Linux | .rpm |
rpm-build (sudo apt install rpm or sudo dnf install rpm-build) |
| Windows | .msi |
WiX Toolset 3.0+ |
| Windows | .exe |
WiX Toolset or Inno Setup |
| macOS | .dmg |
Xcode Command Line Tools (xcode-select --install) |
| macOS | .pkg |
Xcode Command Line Tools |
Add an installerType property to the jpackage task in build.gradle.kts:
val installerType = project.findProperty("installerType")?.toString() ?: "app-image"
// In jpackageArgs:
"--type", installerType,
Then build with:
# Linux .deb
./gradlew jpackage -PinstallerType=deb
# Linux .rpm
./gradlew jpackage -PinstallerType=rpm
# Windows .msi
gradlew.bat jpackage -PinstallerType=msi
# macOS .dmg
./gradlew jpackage -PinstallerType=dmg
To build native installers in CI, you need to install the required tools:
Linux (.deb is available by default, for .rpm):
- name: Install RPM tools
run: sudo apt-get install -y rpm
Windows (.msi requires WiX):
- name: Install WiX Toolset
run: choco install wixtoolset -y
macOS (.dmg/.pkg work by default with Xcode CLI tools)
Edit the javaOptions list in build.gradle.kts:
val javaOptions = listOf(
"-XX:+UseZGC",
"-XX:+UseStringDeduplication",
"-Xmx2g", // Increase max heap
"-Xms512m" // Increase initial heap
)
Ensure you have JDK 21+ installed (not just JRE). The jpackage tool is included in the JDK.
java -version # Should show 21+
which jpackage # Should show path to jpackage
Windows may block unsigned applications. Users need to click "More info" → "Run anyway" on first launch.
For production releases, consider code signing with a certificate.
Unsigned apps are blocked by default. Users can:
For production releases, consider Apple Developer notarization.
Run the full build first:
./gradlew build
./gradlew jpackage