Reference
AppBundler is structured around two concepts: a product spec, which describes how to build a Julia application, and a bundle format, which describes how to package it for distribution on a target platform. These are combined through the bundle function:
bundle(spec, format, destination; password = "")This is also the function exposed to the command-line API, where command-line parameters configure the spec and format fields.
Product Specs
A product spec defines how the application is compiled or staged. There are two kinds:
spec = JuliaImgBundle(project; kwargs...) # stages a self-contained Julia image
spec = JuliaCBundle(project; kwargs...) # compiles a native executable via juliacBoth specs can be staged directly into a directory for inspection before packaging via stage(spec, destination). For JuliaImgBundle, staging is platform-agnostic as long as compilation is not required — cross-platform staging is possible by setting precompile=false and sysimg_packages = [], with the target platform specified via the platform keyword (defaults to HostPlatform()). For JuliaCBundle, the platform is fixed to the host, as determined by the juliac executable on PATH.
Bundle Formats
A bundle format defines the packaging target. The supported formats are DMG (macOS), MSIX (Windows), and Snap and AppImage (Linux). They are instantiated from a project directory:
dmg = DMG(project; arch = Sys.ARCH, kwargs...)
msix = MSIX(project; arch = Sys.ARCH, kwargs...)
snap = Snap(project; arch = Sys.ARCH, kwargs...)
appimage = AppImage(project; arch = Sys.ARCH, kwargs...)AppImage produces a single mountable file rather than an installed tree; see AppImage.
Each format reads configuration file overrides from the corresponding project/meta/<format> directory and carries architecture information that determines the destination platform. Bundle formats can also be staged independently via stage(format, destination) to produce the directory structure before compression and signing.
Low-Level Bundle API
For packaging non-Julia applications, or when you need full control over what goes into the bundle, the lower-level bundle do-block API can be used directly:
bundle(format, destination; password = "") do staging_dir
# copy or compile application files into staging_dir
endThe password argument is the certificate password used to decrypt the signing certificate and perform code signing during the pack step. Non-Julia applications can be bundled this way as well, as long as the user takes care of building and installing the application files in the setup callback.
Types
AppBundler.JuliaImg.JuliaImgBundle — Type
JuliaImgBundle(project; kwargs...)Build specification for staging a Julia application as a self-contained image.
The Julia version is read from Manifest.toml in project (falling back to the running Julia version). Incremental compilation defaults to true when no sysimage packages are requested; building a sysimage forces incremental = false because a new sysimage invalidates all existing pkgimage caches.
Arguments
project::String: Path to the application directory containingProject.tomlandManifest.toml
Keyword Arguments
precompile::Bool = true: Precompile packages during staging. Whenfalse, precompilation is deferred to the first launch on the target systemincremental::Bool = isempty(sysimg_packages): Whether to reuse existing pkgimage caches. Automatically set tofalsewhensysimg_packagesis non-emptysysimg_packages::Vector{String} = []: Packages to bake into the system image. Triggers a full sysimage rebuild, which invalidates all pkgimage cachessysimg_args::Cmd =``: Extra command-line arguments forwarded to the sysimage compilerremove_sources::Bool = false: Strip.jlsource files from the staged package tree (only meaningful when all relevant packages are baked into the sysimage)asset_spec::Dict{Symbol,Vector{String}} = Dict(): Selective asset inclusion rules. When empty, all artifacts are included and indexed viapkgoriginasset_rpath::String = "assets": Destination subdirectory for assets whenasset_specis setstartup_file::String: Path to thestartup.jltemplate. Resolved frommeta/startup.jlinsideproject, falling back to$(pkgdir(AppBundler))/recipes/startup.jl
Examples
# Default: precompile everything, incremental caches
pkg = JuliaImgBundle("path/to/app")
# Skip precompilation — compile on first launch instead
pkg = JuliaImgBundle("path/to/app"; precompile = false)
# Bake heavy dependencies into a sysimage (forces non-incremental rebuild)
pkg = JuliaImgBundle("path/to/app"; sysimg_packages = ["Plots", "DifferentialEquations"])AppBundler.JuliaC.JuliaCBundle — Type
JuliaCBundle(project; kwargs...)Build specification for compiling a Julia application into a native executable via juliac.
Unlike JuliaImgBundle, which stages a full Julia runtime alongside precompiled package images, JuliaCBundle ahead-of-time compiles the application into a standalone native executable. The juliac tool must be installed and is looked up in bin/juliac under each entry of DEPOT_PATH, with ~/.julia/bin as a final fallback.
Arguments
project::String: Path to the application directory containingProject.toml
Keyword Arguments
juliac_cmd::Cmd = Cmd([juliac()]): Command used to invokejuliac. Defaults to the firstjuliacexecutable found onDEPOT_PATHtrim::Bool = false: Whentrue, passes--trim=safetojuliac, removing unreachable code from the output binaryargs::Cmd =`: Additional arguments forwarded verbatim tojuliac`asset_spec::Dict{Symbol,Vector{String}} = Dict(): Selective asset inclusion rules. When empty, no assets are copied into the bundleasset_rpath::String = "assets": Destination subdirectory for assets insidedestination
Examples
# Minimal: compile with defaults
pkg = JuliaCBundle("path/to/app")
# Enable dead-code trimming and a custom executable name
pkg = JuliaCBundle("path/to/app"; executable_name = "myapp", trim = true)AppBundler.DMG AppBundler.Snap AppBundler.AppImage
Functions
AppBundler.stage — Method
stage(product::JuliaImgBundle, destination::String;
platform::AbstractPlatform = HostPlatform(),
cpu_target = get_cpu_target(platform),
runtime_mode = "MIN",
app_name = "",
bundle_identifier = "")Stage a Julia application into destination, ready for packaging and distribution.
The staging process:
- Downloads and extracts the Julia runtime for
platform(version fromManifest.toml) - Copies all non-stdlib packages and artifacts into the stdlib tree
- Configures
startup.jl,DEPOT_PATH, andLOAD_PATHviaAppEnv - Optionally compiles a system image from
product.sysimg_packages - Optionally precompiles pkgimages for all project dependencies
When product.precompile is true, platform must match the host OS and architecture (see cross-compilation constraints below).
Arguments
product::JuliaImgBundle: Staging configurationdestination::String: Directory in which the staged application is assembled
Keyword Arguments
platform::AbstractPlatform: Target platform; defaults to the current hostcpu_target: LLVM CPU target string; derived fromplatformby defaultruntime_mode: AppEnv runtime mode string passed toAppEnv.save_configapp_name: Application name embedded in the AppEnv configbundle_identifier: Bundle identifier embedded in the AppEnv config (e.g. reverse-DNS on macOS)
Cross-Compilation Constraints
Precompilation runs native code, so cross-OS and cross-architecture compilation is not supported when product.precompile = true:
- Windows: host must be Windows
- macOS: host must be macOS;
x86_64 → aarch64is not supported - Linux: host must be Linux with a matching architecture
Set precompile = false and sysimg_packages = [] in JuliaImgBundle to stage for a different platform without compilation.
Examples
pkg = JuliaImgBundle("src/MyApp")
# Stage for the current machine
stage(pkg, "build/staging")
# Stage for macOS arm64 (must run on Apple Silicon with precompile=false, or natively)
stage(pkg, "build/MyApp.app/Contents/Resources/julia";
platform = Platform("aarch64", "macos"))
# Embed app identity in the AppEnv config
stage(pkg, "build/staging"; app_name = "MyApp", bundle_identifier = "com.example.myapp")AppBundler.stage — Method
stage(spec::JuliaCBundle, destination::String;
runtime_mode = "MIN",
app_name = get_module_name(spec.project),
bundle_identifier = "")Compile a Julia application into a native executable and assemble it in destination.
The staging process:
- Saves an AppEnv config to
destination/configwith runtime identity and load-path settings - Installs assets from
spec.asset_specintodestination/<asset_rpath> - Writes a pkgorigin index to
destination/indexfor asset resolution at runtime - Invokes
juliacto AOT-compile the application and bundle the result intodestination
Unlike JuliaImgBundle, no Julia runtime tarball is downloaded — juliac produces a self-contained native binary. The host toolchain must be compatible with the target.
Arguments
spec::JuliaCBundle: Compilation and asset configurationdestination::String: Directory in which the compiled application is assembled
Keyword Arguments
runtime_mode: AppEnv runtime mode string passed toAppEnv.save_configapp_name: Application name embedded in the AppEnv config; defaults to the module namebundle_identifier: Bundle identifier embedded in the AppEnv config (e.g. reverse-DNS on macOS)
Examples
pkg = JuliaCBundle("src/MyApp")
# Stage into a directory
stage(pkg, "build/myapp";
app_name = "MyApp", bundle_identifier = "com.example.myapp")
# Stage with a custom runtime mode
stage(pkg, "build/staging"; runtime_mode = "SANDBOX")AppBundler.stage — Method
stage(config, destination::String; [dsstore=false])Stage package metadata and directory structure into destination in preparation for bundling.
config is a format-specific configuration object — MSIX, DMG, or Snap — that carries the template files, parameters, and settings for the target platform. Mustache-rendered templates are written using the parameters stored in config.
stage is called automatically by bundle, but can be used directly when you need to inspect or modify the staging directory before compression and signing.
Staged layout by format
MSIX
Assets/— application icons (generated from source or copied verbatim if already a directory)AppxManifest.xml— rendered package manifestresources.pri— package resource indexMsix.AppInstaller.Data/MSIXAppInstallerData.xml— rendered installer configuration
DMG
Contents/Resources/icon.icns— application iconContents/Info.plist— rendered application metadataContents/MacOS/<app-name>(optional) — native launcher whenmain_launcheris set
When dsstore = true, also writes into the parent of destination:
Applications— symlink to/Applicationsfor drag-and-drop installation.DS_Store— custom Finder window appearance
Snap
meta/icon.png— application iconmeta/snap.yaml— rendered Snap package metadatameta/gui/<app-name>.desktop— rendered desktop launchermeta/hooks/configure(optional) — configuration hook whenconfigure_hookis setbin/<app-name>(optional) — main launcher script whenmain_launcheris set
Examples
stage(MSIX(app_dir), "build/msix_staging")
stage(DMG(app_dir), "build/MyApp.app"; dsstore = true)
stage(Snap(app_dir), "build/snap_staging")AppBundler.bundle — Method
bundle(setup::Function, config, destination::String; force=false, [password=""])Stage, populate, and optionally compress an application bundle for distribution.
config is a format-specific configuration object — MSIX (Windows), DMG (macOS), or Snap (Linux) — and destination is the path of the final artifact (e.g. "MyApp.msix", "MyApp.dmg", "MyApp.snap") or an uncompressed staging directory.
The function follows three steps:
- Stage — writes platform metadata and directory structure into a staging area via
stage. - Setup — calls
setup(staging_dir), where you copy or compile the application files that should be included in the bundle. - Pack — when
config.compressistrue(the default whendestinationcarries the format extension), compresses the staging area into the final artifact and performs code signing.
Set force = true to overwrite an existing destination path.
Code signing
MSIX and DMG sign the bundle automatically during the pack step. Pass the certificate password via the password keyword argument (defaults to ""). When config.selfsign is true, a temporary self-signed certificate is generated instead of using the one in the configuration. DMG entitlements are rendered from the template stored in the configuration. Snap packages are not signed locally; they are verified by the Snap Store after upload.
Examples
bundle(MSIX(app_dir), "MyApp.msix") do staging_dir
# copy or compile application files into staging_dir
end
bundle(DMG(app_dir), "MyApp.dmg") do staging_dir
# copy or compile application files into staging_dir
end
bundle(Snap(app_dir), "MyApp.snap") do staging_dir
# copy or compile application files into staging_dir
endMissing docstring for AppBundler.bundle(::Function, ::AppBundler.MSIX, ::String). Check Documenter's build log for details.
AppBundler.bundle — Method
bundle(product::JuliaCBundle, appimage::AppImage, destination::String; force = false)Package a juliac-compiled executable as a mountable AppImage.
AppBundler.bundle — Method
bundle(product, packaging, destination; force=false, [password=""])Bundle a Julia application product into a platform-specific package at destination by calling bundle(setup, config, destination) with product staged as the setup step.
Arguments
product: The application artifact to bundle. Either aJuliaImgBundleor aJuliaCBundlepackaging: The target package format. One of:DMG— macOS disk image (.dmg). Must be built on macOS.Snap— Linux Snap package. Must be built on Linux.MSIX— Windows app package (.msix). Must be built on Windows.
destination: Output path for the produced package file.
Keyword Arguments
force=false: Overwrite an existing package atdestinationiftrue.password="": Code-signing certificate password. Applicable toDMGandMSIXtargets only.
A warning is emitted when the host OS does not match the target platform, as cross-platform packaging is not supported.
See also stage, bundle(setup, config, destination).