A Beginner’s Guide to Building Cross-Platform Installers Using IzPack
Overview
IzPack is an open-source Java-based installer generator (Apache 2.0) that creates cross-platform installers (Windows, macOS, Linux, Solaris) requiring only a JVM. It packages application files into “packs”, defines installer UI flow via “panels”, and supports native integrations (shortcuts, registry, elevation) and web installers (packs hosted on a server).
What you’ll build
A simple, reusable installer JAR that:
- Lets users pick target folder
- Select optional components (packs)
- Shows license and progress panels
- Creates an uninstaller
- Optionally creates OS-native shortcuts
Files you need
- install-definition.xml (main installer descriptor)
- Application files organized into pack folders
- Resource files (license, images, localized strings)
- Optional: native libs for shortcuts (Windows)
Minimal install-definition.xml (example)
<?xml version=“1.0” encoding=“ISO-8859-1”?>
<installation version=“1.0”>
<info>
<appname>MyApp</appname>
<appversion>1.0.0</appversion>
<javaversion>1.8</javaversion>
<uninstaller name=“uninstall” path=“\(INSTALL_PATH/Uninstall</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(128, 0, 0);"> </span><span class="token" style="color: rgb(255, 0, 0);">write</span><span class="token attr-equals" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(0, 0, 255);">yes</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(57, 58, 52);">/></span><span> </span><span> </span><span class="token" style="color: rgb(57, 58, 52);"></</span><span class="token" style="color: rgb(128, 0, 0);">info</span><span class="token" style="color: rgb(57, 58, 52);">></span><span> </span><span> </span><span class="token" style="color: rgb(57, 58, 52);"><</span><span class="token" style="color: rgb(128, 0, 0);">guiprefs</span><span class="token" style="color: rgb(128, 0, 0);"> </span><span class="token" style="color: rgb(255, 0, 0);">width</span><span class="token attr-equals" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(0, 0, 255);">640</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(128, 0, 0);"> </span><span class="token" style="color: rgb(255, 0, 0);">height</span><span class="token attr-equals" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(0, 0, 255);">480</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(128, 0, 0);"> </span><span class="token" style="color: rgb(255, 0, 0);">resizable</span><span class="token attr-equals" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(0, 0, 255);">no</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(57, 58, 52);">/></span><span> </span><span> </span><span class="token" style="color: rgb(57, 58, 52);"><</span><span class="token" style="color: rgb(128, 0, 0);">locale</span><span class="token" style="color: rgb(57, 58, 52);">></span><span> </span><span> </span><span class="token" style="color: rgb(57, 58, 52);"><</span><span class="token" style="color: rgb(128, 0, 0);">langpack</span><span class="token" style="color: rgb(128, 0, 0);"> </span><span class="token" style="color: rgb(255, 0, 0);">iso3</span><span class="token attr-equals" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(0, 0, 255);">eng</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(57, 58, 52);">/></span><span> </span><span> </span><span class="token" style="color: rgb(57, 58, 52);"></</span><span class="token" style="color: rgb(128, 0, 0);">locale</span><span class="token" style="color: rgb(57, 58, 52);">></span><span> </span><span> </span><span class="token" style="color: rgb(57, 58, 52);"><</span><span class="token" style="color: rgb(128, 0, 0);">packs</span><span class="token" style="color: rgb(57, 58, 52);">></span><span> </span><span> </span><span class="token" style="color: rgb(57, 58, 52);"><</span><span class="token" style="color: rgb(128, 0, 0);">pack</span><span class="token" style="color: rgb(128, 0, 0);"> </span><span class="token" style="color: rgb(255, 0, 0);">name</span><span class="token attr-equals" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(0, 0, 255);">Core</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(128, 0, 0);"> </span><span class="token" style="color: rgb(255, 0, 0);">required</span><span class="token attr-equals" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(0, 0, 255);">yes</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(57, 58, 52);">></span><span> </span><span> </span><span class="token" style="color: rgb(57, 58, 52);"><</span><span class="token" style="color: rgb(128, 0, 0);">file</span><span class="token" style="color: rgb(128, 0, 0);"> </span><span class="token" style="color: rgb(255, 0, 0);">src</span><span class="token attr-equals" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(0, 0, 255);">dist/myapp.jar</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(128, 0, 0);"> </span><span class="token" style="color: rgb(255, 0, 0);">targetdir</span><span class="token attr-equals" style="color: rgb(57, 58, 52);">=</span><span class="token" style="color: rgb(57, 58, 52);">"</span><span class="token" style="color: rgb(0, 0, 255);">\)INSTALL_PATH”/>
</pack>
<pack name=“Docs” required=“no”>
<file src=“docs” targetdir=“$INSTALL_PATH/docs”/>
</pack>
</packs>
<panels>
<panel classname=“HTMLHelloPanel”/>
<panel classname=“HTMLLicencePanel”/>
<panel classname=“TargetPanel”/>
<panel classname=“PacksPanel”/>
<panel classname=“InstallPanel”/>
<panel classname=“SimpleFinishPanel”/>
</panels>
<resources>
<res id=“Licence” src=“license.txt”/>
</resources>
</installation>
Build steps (prescriptive)
- Organize files: place application files and resources in a working directory.
- Create install-definition.xml (use example above; adjust packs, resources, panels).
- Add license text and any panel images under your resources folder.
- Build installer:
- Using IzPack Ant task:
- Add standalone-compiler.jar to Ant lib.
- Run izpack task: specify input=install-definition.xml, output=MyApp-installer.jar.
- Or use izpack-maven-plugin / izpack CLI per docs.
- Test installer on each target OS with an appropriate JVM installed.
- Add native features:
- Include native libraries (e.g., ShellLink.dll) and ShortcutPanel configuration for Windows.
- Use RegistrySpec for Windows registry entries if needed.
- Create web installer (optional): produce a small installer that downloads packs from a hosted packs JAR.
Tips & best practices
- Keep packs modular so users can skip optional components.
- Use resource IDs for license and localized text; supply langpacks for other locales.
- Use GUI prefs to control size, LAF, and header visuals.
- Automate build in CI (Ant or Maven) to produce reproducible installer artifacts.
- Test console (headless) and GUI modes; provide parity for both.
- For Java 9+ compatibility, ensure IzPack version supports your JDK (use latest stable 5.x/6.x as appropriate).
Useful references
- Official site and docs: https://izpack.org
- Sample install-definition and Ant examples: IzPack documentation/wiki
- Native shortcut and registry examples in docs