A Rust implementation of appimagetool for the Anylinux-AppImages project.
It takes a prepared AppDir and produces a finished .AppImage using DWARFS compression and the uruntime AppImage runtime. Single binary, no Python, no C++ deps.
appimagetool ./AppDirThat's it. The tool will:
- Validate the AppDir (checks for
AppRun,.DirIcon, one.desktopfile). - Download pinned
mkdwarfsanduruntimeif they're not already cached. (The-fullvariants already ship with them). - Write
X-AppImage-*metadata into the desktop entry. - Build the DWARFS image with the runtime embedded as the ELF header.
- Generate a
.zsyncfile when update info is set, plus anappinfosidecar.
- DWARFS compression for small, delta-friendly AppImages.
- Drop-in uruntime integration with automatic download and ELF section patching.
- Optional profile-guided optimization (DWARFS hotness profiling) for faster launches.
- Built-in zsync generation, no
zsyncmakeshell-out. - No central repository, no daemon, no extra runtime deps.
appimagetool ./build/AppDir \
--output ./dist \
--update-info "gh-releases-zsync|org|repo|latest|*-x86_64.AppImage.zsync"If GITHUB_REPOSITORY is set, update info is auto-derived as
gh-releases-zsync|owner|repo|latest|*<arch>.AppImage.zsync. So in CI you usually just need:
VERSION=1.2.3 appimagetool ./AppDir --output ./distThe tool tracks two arches separately:
APPIMAGE_ARCHis the runtime arch. It picks whichuruntimebinary to download, and shows up inX-AppImage-Archmetadata. Defaults to the host arch.ARCHis the display arch. It only affects the output filename. Falls back toAPPIMAGE_ARCHwhen unset.
Neither affects mkdwarfs: it is executed on the build host, so it is resolved for the host arch unless overridden by --mkdwarfs or --dwarfs-url.
This lets a project publish under an alias like amd64 while still pulling the correct x86_64 runtime:
APPIMAGE_ARCH=x86_64 ARCH=amd64 appimagetool ./AppDir
# produces MyApp-1.2.3-anylinux-amd64.AppImage with X-AppImage-Arch=x86_64Usage: appimagetool [OPTIONS] [APPDIR]
Arguments:
[APPDIR] Path to the AppDir directory [env: APPDIR] [default: ./AppDir]
Options:
-o, --output <OUTPUT> Output directory [env: OUTPATH] [default: .]
-n, --name <NAME> Output filename (auto-detected from .desktop) [env: OUTNAME]
--appimage-arch <ARCH> Runtime arch (uruntime download URL + X-AppImage-Arch) [env: APPIMAGE_ARCH]
--arch <ARCH> Display arch used in the output filename [env: ARCH]
--runtime <RUNTIME> Path to uruntime binary [env: RUNTIME]
--runtime-url <URL> URL to download uruntime from [env: URUNTIME_LINK]
-u, --update-info <UPINFO> Update information string [env: UPINFO]
--dwarfs-comp <COMP> DWARFS compression options [env: DWARFS_COMP]
--optimize-launch Enable DWARFS profile optimization (also via OPTIMIZE_LAUNCH=1)
--profile-timeout <SECS> Profiling timeout in seconds [env: OPTIMIZE_LAUNCH_TIMEOUT] [default: 10]
--keep-mount Keep the FUSE mount alive after exit (also via URUNTIME_PRELOAD=1)
--devel-release Tag the build as a nightly/devel release (also via DEVEL_RELEASE=1)
--dwarfs-profile <PROFILE> Path to DWARFS profile [env: DWARFSPROF]
--mkdwarfs <PATH> Path to mkdwarfs binary [env: DWARFS_CMD]
--dwarfs-url <URL> URL to download mkdwarfs from [env: DWARFS_LINK]
--tmpdir <TMPDIR> Temporary directory [env: TMPDIR] [default: /tmp]
--license Print license and third-party notices for this build
-v, --verbose... Increase verbosity (-v, -vv)
-q, --quiet... Suppress informational output (-q, -qq)
-h, --help Print help
-V, --version Print version
Every CLI option has a matching env var (shown above). A few extra knobs that are env-only:
| Variable | Effect |
|---|---|
VERSION |
Version string baked into the AppImage filename and metadata. |
APPNAME |
Override the application name (defaults to the desktop entry's Name). |
GITHUB_REPOSITORY |
When set, auto-generates update_info as gh-releases-zsync|owner|repo|latest|... |
ADD_PERMA_ENV_VARS |
Permanent env vars to bake into the runtime, one per line. |
URUNTIME_PRELOAD |
Set to 1 to keep the FUSE mount after the app exits. |
DEVEL_RELEASE |
Set to 1 to tag the build as a nightly/devel release. |
OPTIMIZE_LAUNCH |
Set to 1 to enable the DWARFS profiling pass (same as --optimize-launch). |
OPTIMIZE_LAUNCH_TIMEOUT |
Profiling timeout in seconds (default 10). |
SKIP_INTEGRITY_CHECKS |
Set to 1 to skip the pinned uruntime SHA-256 verification. |
Without --dwarfs-comp / DWARFS_COMP, the default is zstd:level=22 -B2 plus a block size (-S) derived from the AppDir:
- The size is the sum of the regular files under the AppDir, read right before
mkdwarfsruns. mkdwarfscompresses blocks in parallel, one block per worker. The default is the smallest block size that gives at most 4 blocks (the vCPUs of a hosted CI runner), clamped to-S24(16 MiB) ..-S26(64 MiB).- That is
-S24up to 64 MiB,-S25up to 128 MiB, and-S26above. If the size cannot be read,-S26is used. - Machines with more than 4 cores keep idle workers until the AppDir is several hundred MiB. Pass
--dwarfs-compto choose differently. - Smaller blocks cost image size. On one 54 MiB GUI app
-S24was 2.1% to 2.3% larger than-S26. On a binary-heavy 53 MiB tree it was 4.35% larger. Image size is the price of the faster build. - The default therefore changes with the AppDir size, and an AppDir that crosses 64 MiB or 128 MiB between releases is re-blocked, which makes the next zsync update download most of the image.
To keep the previous fixed default:
appimagetool --dwarfs-comp 'zstd:level=22 -S26 -B2' ./AppDirAn explicit --dwarfs-comp is passed to mkdwarfs unchanged.
The AppDir must contain:
- An executable
AppRun. - A
.DirIconfile (PNG or SVG). - Exactly one
.desktopfile in the AppDir root.
By default:
<AppName>-<Version>-anylinux-<Arch>.AppImage
Where AppName comes from the .desktop Name key (or APPNAME), Version from VERSION (or ~/version), and Arch is the display arch (ARCH, falling back to APPIMAGE_ARCH).
You can also pin the filename outright with --name / OUTNAME.
cargo build --releaseBy default appimagetool downloads its helpers on demand: the pinned uruntime
always, and mkdwarfs only when it is not already on $PATH. Two optional
features bake them into the binary instead, so a build needs no network access
at AppImage build time.
# Embed the pinned uruntime. Stays MIT.
cargo build --release --features embed-uruntime
# Also embed mkdwarfs. See the licensing note below before using this.
cargo build --release --features embed-uruntime,embed-mkdwarfsRelease artifacts ship in two variants. appimagetool-<arch> is built with no
features: it is MIT and downloads its helpers on demand. appimagetool-full-<arch>
is built with both features, so it needs no network at all for helper
resolution — which makes it GPL-3.0-or-later. See Licensing.
Embedded blobs are architecture specific: the uruntime blob is used only when
--appimage-arch matches the build's target, the mkdwarfs blob only when the
host arch does. An explicit --runtime / --mkdwarfs path or a custom
--runtime-url / --dwarfs-url always wins over an embedded copy.
build.rs resolves each blob in this order, verifying the pinned SHA-256 at
every step:
- an explicit path in
URUNTIME_EMBED_PATH/MKDWARFS_EMBED_PATH, or a file named{uruntime,mkdwarfs}-{arch}insideAPPIMAGETOOL_EMBED_DIR - a digest-valid file in the in-tree
.embed-cache/directory - a download from the pinned upstream URL
Packagers building in a network-isolated sandbox should pre-fetch the artifact and use step 1, which never reaches the network:
URUNTIME_EMBED_PATH=/path/to/uruntime-x86_64 \
cargo build --release --features embed-uruntimeA default build runs no network requests in build.rs at all, so it works
unchanged on docs.rs and in distro build sandboxes.
appimagetool's own source is MIT in every configuration. The embed-mkdwarfs
feature changes the license of the resulting binary, because DwarFS is split
licensed: the code that reads images is MIT, while the mkdwarfs writer is
GPL-3.0.
| Build | Embedded | Binary license |
|---|---|---|
| default | nothing | MIT |
embed-uruntime |
uruntime + DwarFS reader | MIT |
embed-mkdwarfs |
dwarfs-universal |
GPL-3.0-or-later |
embed-uruntime is MIT throughout because it pins the -lite uruntime variant,
which carries only DwarFS dwarfs-fuse-extract (the MIT reader and extractor)
rather than dwarfs-universal.
The appimagetool-full-<arch> artifacts published on the releases page are
GPL-3.0-or-later, because they are built with embed-mkdwarfs. The plain
appimagetool-<arch> artifacts are MIT and download their helpers on demand.
Each release therefore also ships the DwarFS Corresponding Source as
appimagetool-corresponding-source-dwarfs-<version>.tar.xz, and the
appimagetool-full-<arch> tarballs include licenses/, which holds the full
GPL-3.0 text along with the MIT notices for uruntime and the DwarFS reader.
If you need an MIT-licensed binary, use the plain appimagetool-<arch>
artifact or build from source without embed-mkdwarfs. The crate source itself
is MIT in every configuration, so cargo build --release or
--features embed-uruntime both give you an MIT artifact.
Anyone redistributing a GPL-3.0 build is conveying a GPL-3.0 work and must keep
that Corresponding Source available to recipients for as long as the binary is
offered. See licenses/mkdwarfs-GPL-3.0.txt for the details.
appimagetool --license reports the effective license of any build along with
the notices for whatever that build actually embeds.
# Unit + integration tests
cargo test --all-features
# Full end-to-end test (requires mkdwarfs + uruntime installed)
cargo test --all-features -- --ignoredbuild.rs resolves the optional embedded helper blobs
licenses/ notices shipped with builds that embed a helper
src/
├── main.rs CLI entry point (clap)
├── lib.rs library root
├── appimage.rs build pipeline orchestration
├── config.rs CLI args + env var resolution
├── desktop.rs .desktop parsing and metadata
├── dwarfs.rs mkdwarfs resolution, image building, profiling
├── elf.rs ELF section read / write / patch
├── embed.rs embedded helper access + license reporting
├── error.rs error types with actionable hints
├── log.rs verbosity-gated logger
├── pinned.rs pinned upstream URLs + SHA-256 digests (shared with build.rs)
├── uruntime.rs runtime download, caching, configuration
└── util.rs atomic downloads, sanitization, ELF detection