Skip to main content

UPX Compression

Compress binaries with UPX to reduce download size

UPX (the Ultimate Packer for eXecutables) compresses compiled binaries in-place, often reducing them to 30-50% of their original size. Anodizer runs UPX immediately after the build stage and before archiving, so the smaller binaries flow into your archives, checksums, and releases automatically.

Minimal config

upx:
  enabled: true

This compresses every binary artifact using the default upx binary on your PATH with no extra flags. If upx is not installed, the stage logs a warning and continues.

Config fields

The upx key accepts a single object or an array of objects. Each object supports the following fields:

FieldTypeDefaultDescription
idstringnoneUnique identifier for this UPX config (used in log output)
idslist of stringsnoneOnly compress binaries whose build id (or binary name) is in this list. Omit to compress all binaries.
enabledbool or template stringnone (treated as disabled)Whether this config is active. Supports template strings for conditional evaluation (e.g., "{{ IsRelease }}")
binarystring"upx"Path or name of the UPX executable
compressstringnoneCompression level: "1" through "9", or "best" (maps to --best)
lzmaboolfalseEnable LZMA compression (--lzma flag)
bruteboolfalseEnable brute-force compression (--brute flag). Very slow but produces the smallest output.
argslist of strings[]Additional raw arguments passed to UPX after all other flags
targetslist of glob patternsnoneOnly compress binaries built for matching target triples. Omit to compress all targets.
requiredboolfalseWhen true, fail the build if the UPX binary is not found. When false, skip with a warning.

The enabled field must be explicitly set to true (or a template that evaluates to true) for the config to take effect. An omitted or null enabled field is treated as disabled.

Examples

Basic compression with best settings

upx:
  enabled: true
  compress: best
  lzma: true

Only compress Linux binaries

upx:
  enabled: true
  compress: best
  targets:
    - "*-linux-*"

Different settings per platform

Use an array to define multiple UPX configs that each target different platforms:

upx:
  - id: linux
    enabled: true
    compress: best
    lzma: true
    targets:
      - "x86_64-*-linux-*"
      - "aarch64-*-linux-*"

  - id: windows
    enabled: true
    compress: "9"
    targets:
      - "*-windows-*"

Filter by build ID

If your project produces multiple binaries and you only want to compress some of them:

upx:
  enabled: true
  ids: ["myapp", "myapp-cli"]
  compress: best

Require UPX in CI

upx:
  enabled: true
  required: true
  compress: best

With required: true, the build fails immediately if upx is not found on the system. This is useful in CI where a missing tool should be a hard error rather than a silent skip.

Custom UPX binary path

upx:
  enabled: true
  binary: /usr/local/bin/upx
  args:
    - "--best"
    - "--lzma"

Target filtering

The targets field accepts glob patterns matched against Rust target triples. The * wildcard matches any sequence of characters. When targets is set, only binaries whose target triple matches at least one pattern are compressed. Binaries with no target metadata are skipped when a targets filter is present.

Common patterns:

PatternMatches
"*-linux-*"All Linux targets
"*-windows-*"All Windows targets
"*-apple-darwin"All macOS targets
"x86_64-*"All x86_64 targets
"aarch64-*"All AArch64/ARM64 targets
"*"Everything (same as omitting targets)

Note that UPX itself does not support every executable format. If UPX encounters a binary it cannot compress (for example, a format it does not recognize), it reports a known exception such as CantPackException or UnknownExecutableFormatException. Anodizer treats these as warnings and skips the binary rather than failing the build.

Pipeline position

UPX runs as the second stage in the pipeline, immediately after the build stage and before changelog generation and archiving:

build -> upx -> changelog -> archive -> ...

This means compressed binaries are what end up in your .tar.gz, .zip, and other archive formats. Checksums, SBOMs, and signatures all reflect the compressed binary sizes.

In --split mode (where build and release are separate steps), UPX is included in the build-only pipeline, so the compressed artifacts are available for the later release step.

Parallel compression

Anodizer compresses matching binaries in parallel, bounded by the global --parallelism setting. Each chunk of binaries is processed concurrently using threads, matching the parallelism model used by other stages.

Dry run

When running with --dry-run, the UPX stage logs what it would compress (including the flags it would use) without actually invoking UPX or modifying any files.