I am excited to announce AppBundler.jl
The package offers recipes for building Julia GUI applications in modern desktop application installer formats. It uses Snap for Linux, MSIX for Windows, and DMG for MacOS as targets. It bundles full Julia within the app, which, together with artifact caching stored in scratch space, allows the bundling to be done quickly, significantly shortening the feedback loop.
The build product of AppBundler.jl
is a bundle that can be conveniently finalised with a shell script on the corresponding host system without an internet connection. This allows me to avoid maintaining multiple Julia installations for different hosts and reduces failures due to a misconfigured system state. It is ideal for a Virtualbox setup where the bundle together with bundling script is sent over SSH after which the finalised installer is retrieved.
The configuration options for each installer bundle vary greatly and are virtually limitless; thus, creating a single bundling configuration file for all systems is impractical. To resolve this, the AppBundler recipe system comes into the picture. AppBundler provides default configuration files which substitute a few set variables specified at the Project.toml
in a dedicated [bundle]
section. This shall cover plenty of use cases. In case the application needs more control, like interfacing web camera, speaker, host network server, etc., the user can place a custom snap.yaml
, AppxManifest.xml
and Entitlements.plist
in the application meta
folder, overloading the defaults. Additional files can be provided easily for the bundle by placing them in a corresponding folder hierarchy. For instance, this can be useful for providing custom-sized icon sizes. To see how that works, explore AppBundler.jl/examples and PeaceFounderClient where you can check out the releases page to see what one can expect.
All recipes define a USER_DATA
environment variable where apps can store their data. On Linux and Windows those are designated application locations which get removed with the uninstallation of the app, whereas on MacOS, apps use ~/.config/myapp
and ~/.cache/myapp
folders unless one manages to get an app running from a sandbox in which case the $HOME/Library/Application Support/Local
folder will be used.
Thought has also been put into improving the precompilation experience to reduce start-up time for the first run. For MacOS, precompilation can be done before bundling in the /Applications
folder by running MyApp.app/Contents/MacOS/precompile
. For Linux, precompilation is hooked into the snap configure hook executed after installation. For Windows, a splash screen is shown during the first run, providing user feedback that something is happening. Hopefully, the cache relocability fix in Julia 1.11 will allow us to precompile the Windows bundle as well.
The most challenging aspect of this package is crafting recipes. So far, I have yet to manage to get sandboxing to work on either platform which prevents applications from being accepted in corresponding marketplaces. In particular, the issues are:
- Windows can start Julia and crash immediately. See issue #52007
- MacOS can start GUI but is unresponsive. Present in both GTK and QML.
- Linux can start GLWF by linking with the mesa-core22 snap content package. GTK apps with mesa-core22 segfaults, but works if unlinked. QML draws a window but does not render content #191
It would probably be reasonable to integrate PackageCompiler.jl
for completeness and to resolve the sandboxing issues with Windows and MacOS in that way. One MacOS application is still standing in the Mac app store developed with now deprecated ApplicationBuilder.jl so the path is clear. However, at the moment, I am only considering investing time in it once PackageCompiler issue #164 is resolved, as there would be no benefit for the PeaceFounder project.
Another avenue worth exploring could be making a GitHub workflow, but making a Windows build setup seems like a pain in the ass. At the moment, I am doing postprocessing with shell scripts for MacOS and Windows.