Skip to content

Instantly share code, notes, and snippets.

@ruario
Last active December 31, 2025 14:03
Show Gist options
  • Select an option

  • Save ruario/5050104aed22d066ffc5fb5c62c8f9c9 to your computer and use it in GitHub Desktop.

Select an option

Save ruario/5050104aed22d066ffc5fb5c62c8f9c9 to your computer and use it in GitHub Desktop.
Running RAR for Linux on arm64

Running RAR for Linux on arm64

TL;DR This guide shows how to run the x86_64 Linux RAR binary on arm64 using QEMU user-mode or FEX¹, and compares their performance. If you do not want to read further, simply install either of them via your package manager and then run the script included with this gist, to automatically download, configure and install RAR.

¹ FEX only adds about 13% overhead.

Intro

RAR is a strong archiving option on Linux when you need features other formats do not provide, such as built‑in recovery records, archive‑level deduplication, robust multi‑volume handling, advanced filters, archive content search & manipulation, strong encryption, etc. [Full comparison with other Linux archivers]

Unfortunately there is currently no native arm64 Linux build of RAR, so the only practical way to run it on an arm64 system is to execute the official x86_64 binary through an emulation or translation layer. Below are two approaches: running RAR under QEMU user‑mode and running it under FEX. QEMU user‑mode is designed to run many different CPU architectures, so it prioritizes flexibility. FEX is built specifically for running x86‑64 apps on ARM64, so it can optimize heavily for that one job and run them much faster.

After setting these up, I ran a series of benchmarks to estimate the performance impact of each method compared to a hypothetical native arm64 Linux RAR binary. FEX appears to be only about 13% slower than native performance for this type of workload, while QEMU was a little over twice as slow (~2.1×). That said, QEMU has been around longer, is more battle‑tested and is available on more distros out of the box, so I think it is worth listing both approaches despite FEX being more performant.

Shared prerequisites (RAR + minimal x86_64 runtime)

RAR is dynamically linked, so we need both the binary and a minimal x86_64 runtime environment. The included runtime comes from Debian 11 (Bullseye) because its glibc version is stable and broadly compatible with RAR. Newer Debian releases are not required and may introduce unnecessary incompatibilities. I have included a script with this gist (below) to fetch and install RAR and the runtime libraries. Alternatively here are the manual steps, should you prefer.

  • Fetch and Install the RAR binary (version 7.12 is the latest version as of 2025-12-28)
wget https://www.rarlab.com/rar/rarlinux-x64-712.tar.gz
tar xf rarlinux-x64-712.tar.gz
sudo install -Dm755 rar/rar /usr/local/lib/rar-x64/bin/rar
  • Install your RAR license file (you should already have this locally)
sudo install -m644 rarreg.key /usr/local/etc/rarreg.key
  • Fetch x86_64 runtime packages
wget https://ftp.debian.org/debian/pool/main/g/glibc/libc6_2.31-13+deb11u11_amd64.deb \
     https://ftp.debian.org/debian/pool/main/g/gcc-10/libgcc-s1_10.2.1-6_amd64.deb \
     https://ftp.debian.org/debian/pool/main/g/gcc-10/libstdc++6_10.2.1-6_amd64.deb
  • Extract files to a staging directory (requires ar from GNU Binutils)
mkdir rar-libs-x64
for d in lib*amd64.deb; do 
  ar p $d data.tar.xz | tar xCJ rar-libs-x64
done
  • Fix up one symlink to make it relative
ln -fs ../lib/x86_64-linux-gnu/ld-2.31.so rar-libs-x64/lib64/ld-linux-x86-64.so.2
  • Install the required x86_64 runtime libraries
cd rar-libs-x64
sudo cpio -pLdR0:0 /usr/local/lib/rar-x64 <<-EOF
	lib64/ld-linux-x86-64.so.2
	lib/x86_64-linux-gnu/libc.so.6
	lib/x86_64-linux-gnu/libdl.so.2
	lib/x86_64-linux-gnu/libgcc_s.so.1
	lib/x86_64-linux-gnu/libm.so.6
	lib/x86_64-linux-gnu/libpthread.so.0
	lib/x86_64-linux-gnu/librt.so.1
	usr/lib/x86_64-linux-gnu/libstdc++.so.6
EOF

QEMU user‑mode

QEMU user‑mode runs individual binaries from one CPU architecture on another by translating instructions and emulating system calls. It aims for broad compatibility rather than maximum performance.

  • Install QEMU user-mode
sudo apt update
sudo apt install qemu-user-static
printf '%s\n' '#!/bin/sh' 'exec qemu-x86_64-static -L /usr/local/lib/rar-x64 /usr/local/lib/rar-x64/bin/rar "$@"' | \
  sudo tee /usr/local/bin/rar >/dev/null
sudo chmod +x /usr/local/bin/rar
  • Test
rar -?

FEX

FEX also runs x86‑64 Linux binaries on ARM64, but uses a modern JIT, syscall translation, and aggressive library call forwarding to achieve higher performance.

  • Install FEX
sudo apt install software-properties-common
sudo add-apt-repository ppa:fex-emu/fex
sudo apt update
sudo apt install fex-emu-armv8.0

Note: There are alternative packages to fex-emu-armv8.0, which might perform better if you have the hardware to support them. Below are some examples, but if you’re unsure, fex-emu-armv8.0 should work on all hardware and is the safe option.

Device / SoC ARM Architecture Level FEX Package
Raspberry Pi 5 ARMv8.2 fex-emu-armv8.2
Ampere Altra ARMv8.2 fex-emu-armv8.2
Apple Silicon ARMv8.4 fex-emu-armv8.4
Qualcomm Snapdragon ARMv8.4 fex-emu-armv8.4
printf '%s\n' '#!/bin/sh' 'export FEX_ROOTFS=/usr/local/lib/rar-x64' 'exec FEX /usr/local/lib/rar-x64/bin/rar "$@"' | \
  sudo tee /usr/local/bin/rar >/dev/null
sudo chmod +x /usr/local/bin/rar
  • Test
rar -?

Overhead estimation

I performed the following on an Apple M1 MacBook using the same (725 MB) file as test data. To estimate the overhead of QEMU and FEX, I first measured native RAR compressing this file on macOS arm64 (≈ 28 seconds). I then measured the general slowdown when running Linux arm64 inside Parallels (a virtual machine that lets you run Linux under macOS).

Because RAR doesn't exist for Linux arm64, I used 7‑Zip as a stand‑in since it performs similar compression and runs natively on both macOS arm64 and Linux arm64 (both tools are CPU‑bound and use broadly comparable algorithms). 7‑Zip on Linux arm64 took ~40% longer than on macOS arm64, so I scaled the native macOS RAR time accordingly: 28 s × 1.4 ≈ 39 seconds.

I then compared that estimate to the actual compression times of the official x86_64 RAR binary under QEMU user‑mode and FEX. The results are summarised below.

Method Measured Time Overhead (Estimate)
QEMU user‑mode 83s ~2.1× slower
FEX 44s ~13% slower

The overhead values show how much slower each method is compared to the estimated performance of a native arm64 Linux RAR binary. QEMU is significantly slower for this workload, while FEX comes much closer to native performance.

Note: I also tested Linux x86_64 7‑Zip using both QEMU and FEX and compared those to Linux arm64 7-Zip. Those results closely matched the overhead patterns above, which gives me confidence that the FEX/QEMU overheads are representative for this type of workload.

#!/usr/bin/env bash
# This script installs RAR. On non x64 systems it also install the runtime libs
# needed to run the x64 Linux binary and will create launchers for either QEMU
# user-mode or FEX depending which is installed (FEX is preffered if both are
# installed).
#
# Note: After this script completes it will list where everything was installed.
# It also provides both update and removal scripts.
# Define file install locations
if [ -w /usr/local ]; then
# Installs to these locations, when run with escalated privileges:
# RAR (+unRAR): either the original binaries (x64) or launcher scripts
RAR_BIN_DIR=/usr/local/bin
# Various documentation, including the long user manual
RAR_DOC_DIR=/usr/local/share/doc/rar
# Original x64 binaries and runtime libraries (only installed here on non-x64)
RAR_NON_NATIVE_DIR=/usr/local/lib/rar-x64
# File order list for solid archiving (which can improve compression)
RAR_ORDER_PATH=/etc/rar/rarfiles.lst
# Self-extractor stub (allows creation of x64 Linux self-extracting archives)
RAR_SFX_PATH=/usr/local/lib/default.sfx
# License key (only installed if the key is found in the current working directory)
RAR_KEY_PATH=/etc/rar/rarreg.key
else
# Installs to these locations, when run as a regular user:
RAR_BIN_DIR="$HOME/.local/bin"
RAR_DOC_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/doc/rar"
RAR_NON_NATIVE_DIR="$HOME/.local/lib/rar-x64"
RAR_ORDER_PATH="$HOME/rarfiles.lst"
RAR_SFX_PATH="$HOME/default.sfx"
RAR_KEY_PATH="$HOME/.rarreg.key"
fi
# Install scripts
# Upper case names so the do not clash with autocompleting 'rar'
# If these are run, it is very deliberate by the user
RAR_UPGRADE_SCRIPT="$RAR_BIN_DIR/RAR-upgrade.sh"
RAR_REMOVAL_SCRIPT="$RAR_BIN_DIR/RAR-remove.sh"
# Exit early on errors or missing variables
set -eu
# Set the absolute path to this script
THIS_SCRIPT="${BASH_SOURCE[0]}"
case "$THIS_SCRIPT" in
/*) ;; # Already absolute
*/*) THIS_SCRIPT="$PWD/$THIS_SCRIPT" ;; # Relative path
*)
if [ -e "$THIS_SCRIPT" ]; then
# Run via: bash filename
THIS_SCRIPT="$PWD/$THIS_SCRIPT"
else
# Called via $PATH
THIS_SCRIPT="$(command -v "$THIS_SCRIPT")"
fi
;;
esac
THIS_SCRIPT="$(realpath "$THIS_SCRIPT")" # Normalise the path
# On non-x64 systems check if FEX is installed, if not QEMU user-mode
available () {
command -v "$1" >/dev/null 2>&1
}
if [ "$(uname -m)" = x86_64 ]; then
MODE=native
MODE_PRETTY='Native [x64]'
elif available FEX; then
MODE=fex
MODE_PRETTY='FEX Emulator'
elif available qemu-x86_64-static; then
MODE=qemu
MODE_PRETTY='QEMU user-mode'
else
echo "You must install either FEX or QEMU user-mode first" >&2
exit 1
fi
# Check that `ar` is installed (needed for deb package extraction)
if ! available ar; then
echo "You must install ar (provided by GNU Binutils)" >&2
exit 1
fi
# Check we have a downloader
if available curl; then
CHECK='curl -s'
FETCH='curl -O'
elif available wget; then
CHECK='wget -qO-'
FETCH=wget
else
echo "You need to install cURL or Wget to retrieve packages; exiting" >&2
exit 1
fi
# RAR Labs provide no API or official, reliable source for checking the
# latest version. However I looked carefully at archive.org and the
# following would have worked reliably for the last 20+ years!
RAR_VERSION="$($CHECK https://www.rarlab.com/download.htm | sed -n 's/.*RAR for Linux x64 \([0-9.]\+\)<.*/\1/p;s/.*RAR \([0-9.]\+\) for Linux x64<.*/\1/p' | head -n 1)"
# If that does fail however, fall back to 7.12 and let the user know, what
# happened.
if [ -z "$RAR_VERSION" ]; then
RAR_VERSION=7.12
echo "Could not work out the current RAR version. Using 7.12 (last verrified as the latest: 2025-12-31)" >&2
fi
# Check if the latest is already installed
if [ -r "$RAR_DOC_DIR/VERSION" ]; then
. "$RAR_DOC_DIR/VERSION"
if [ "${INSTALLED_VERSION:-0}" = "$RAR_VERSION" ]; then
echo "RAR $RAR_VERSION is already installed"
exit
else
RAR_UPGRADE=YES
fi
fi
# Switching to a working directory
CWD="$PWD"
TMPDIR="$(mktemp -d)"
cd "$TMPDIR"
# Clean up working directory on exit
trap 'cd "$CWD"; rm -r "$TMPDIR"' EXIT
# Fetch, extract and install all the packages we need (use a local copy of RAR if present)
if [ -r "$CWD/rarlinux-x64-${RAR_VERSION//./}.tar.gz" ]; then
ln -s "$CWD/rarlinux-x64-${RAR_VERSION//./}.tar.gz" "rarlinux-x64-${RAR_VERSION//./}.tar.gz"
else
printf "\n%s\n\n" "Fetching the official RAR binary ($RAR_VERSION-x64)"
$FETCH "https://www.rarlab.com/rar/rarlinux-x64-${RAR_VERSION//./}.tar.gz"
fi
echo "Extracting RAR ($RAR_VERSION)..."
tar xf "rarlinux-x64-${RAR_VERSION//./}.tar.gz"
# Remove the old version before any upgrade
if [ "${RAR_UPGRADE:-NO}" = YES ] && [ -x "$RAR_REMOVAL_SCRIPT" ]; then
printf "\n%s\n\n" "Removing old RAR (${INSTALLED_VERSION:-UNKNOWN}) before installing $RAR_VERSION:"
RAR_UPGRADE=YES "$RAR_REMOVAL_SCRIPT" ||:
echo ''
fi
if [ "$MODE" = "native" ]; then
# Install rar/unrar
install -Dm755 rar/rar "$RAR_BIN_DIR/rar"
install -m755 rar/unrar "$RAR_BIN_DIR"
else
# Install rar/unrar
install -Dm755 rar/rar "$RAR_NON_NATIVE_DIR/bin/rar"
install -m755 rar/unrar "$RAR_NON_NATIVE_DIR/bin"
# Only install the Runtime libs if they are actually needed
if [ -z "${RAR_UPGRADE:-}" ] || [ ! -d "$RAR_NON_NATIVE_DIR/lib" ]; then
# Sticking to a fixed runtime because this has been tested with recent
# RAR versions (last checked: 2025-12-31). I am confident it is likely
# to work for many years to come. Trying to update this dynamically is
# more likely to lead to issues.
echo "Fetching x64 Runtime packages (from Debian 11 [Bullseye])"
# Need runtime as not native
$FETCH https://ftp.debian.org/debian/pool/main/g/glibc/libc6_2.31-13+deb11u11_amd64.deb
$FETCH https://ftp.debian.org/debian/pool/main/g/gcc-10/libgcc-s1_10.2.1-6_amd64.deb
$FETCH https://ftp.debian.org/debian/pool/main/g/gcc-10/libstdc++6_10.2.1-6_amd64.deb
# Since the runtime libraries are fixed, we can use hardcoded checksums
# to verify them.
if ! sha256sum --status -c <<-SUMS
05f7264da867b37f4c5ce49266b558ea1e81e05a9464f623152fca70f3550282 libc6_2.31-13+deb11u11_amd64.deb
e478f2709d8474165bb664de42e16950c391f30eaa55bc9b3573281d83a29daf libgcc-s1_10.2.1-6_amd64.deb
5c155c58935870bf3b4bfe769116841c0d286a74f59eccfd5645693ac23f06b1 libstdc++6_10.2.1-6_amd64.deb
SUMS
then
echo "The checksums for the x64 Runtime libs do not match what was expected; exiting early" >&2
exit 1
fi
echo "Extracting Runtime..."
for deb in *deb; do
ar p "$deb" data.tar.xz | tar xJ
done
# Install runtime libs
install -Dm644 lib/x86_64-linux-gnu/ld-2.*.so "$RAR_NON_NATIVE_DIR/lib/ld-linux-x86-64.so.2"
install -m644 lib/x86_64-linux-gnu/libc-2.*.so "$RAR_NON_NATIVE_DIR/lib/libc.so.6"
install -m644 lib/x86_64-linux-gnu/libdl-2.*.so "$RAR_NON_NATIVE_DIR/lib/libdl.so.2"
install -m644 lib/x86_64-linux-gnu/libgcc_s.so.1 "$RAR_NON_NATIVE_DIR/lib"
install -m644 lib/x86_64-linux-gnu/libm-2.*.so "$RAR_NON_NATIVE_DIR/lib/libm.so.6"
install -m644 lib/x86_64-linux-gnu/libpthread-2.*.so "$RAR_NON_NATIVE_DIR/lib/libpthread.so.0"
install -m644 lib/x86_64-linux-gnu/librt-2.*.so "$RAR_NON_NATIVE_DIR/lib/librt.so.1"
install -m644 usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.* "$RAR_NON_NATIVE_DIR/lib/libstdc++.so.6"
ln -fns lib "$RAR_NON_NATIVE_DIR/lib64"
fi
# Setup launch wrapper scripts for non native modes
printf '%s\n\n' "Setting up launcher for: $MODE_PRETTY"
mkdir -p "$RAR_BIN_DIR"
if [ "$MODE" = "qemu" ]; then
printf \
"%s\n" \
"#!/bin/sh" \
"exec qemu-x86_64-static -L \"$RAR_NON_NATIVE_DIR\" \"$RAR_NON_NATIVE_DIR/bin/rar\" \"\$@\"" \
> "$RAR_BIN_DIR/rar"
printf \
"%s\n" \
"#!/bin/sh" \
"exec qemu-x86_64-static -L \"$RAR_NON_NATIVE_DIR\" \"$RAR_NON_NATIVE_DIR/bin/unrar\" \"\$@\"" \
> "$RAR_BIN_DIR/unrar"
elif [ "$MODE" = "fex" ]; then
printf \
"%s\n" \
"#!/bin/sh" \
"export FEX_ROOTFS=\"$RAR_NON_NATIVE_DIR\"" \
"exec FEX \"$RAR_NON_NATIVE_DIR/bin/rar\" \"\$@\"" \
> "$RAR_BIN_DIR/rar"
printf \
"%s\n" \
"#!/bin/sh" \
"export FEX_ROOTFS=\"$RAR_NON_NATIVE_DIR\"" \
"exec FEX \"$RAR_NON_NATIVE_DIR/bin/unrar\" \"\$@\"" \
> "$RAR_BIN_DIR/unrar"
fi
chmod 755 "$RAR_BIN_DIR"/{rar,unrar}
fi
# Install sfx stub
install -Dm755 rar/default.sfx "$RAR_SFX_PATH"
# Only in install order list for solid archiving if it is not present
# because this is an editable config file
if [ -e "$RAR_ORDER_PATH" ]; then
echo "Warning: Not replacing the solid order list: $RAR_ORDER_PATH" >&2
else
install -Dm644 rar/rarfiles.lst "$RAR_ORDER_PATH"
fi
# Install docs
mkdir -p "$RAR_DOC_DIR"
cp rar/*.{txt,htm*} "$RAR_DOC_DIR"
echo "INSTALLED_VERSION='$RAR_VERSION'" > "$RAR_DOC_DIR/VERSION"
chmod 644 "$RAR_DOC_DIR"/*
# Install license key if it is present locally and not already installed
if [ -e "$CWD/rarreg.key" ]; then
if [ -e "$RAR_KEY_PATH" ]; then
echo "Warning: Not replacing the license key: $RAR_KEY_PATH" >&2
else
install -Dm644 "$CWD/rarreg.key" "$RAR_KEY_PATH"
fi
fi
# Install the current script as an upgrade script, if not already present
if [ "$THIS_SCRIPT" != "$RAR_UPGRADE_SCRIPT" ]; then
install -m755 "$THIS_SCRIPT" "$RAR_UPGRADE_SCRIPT"
fi
# Create a removal script
cat <<-UNINSTALL > "$RAR_REMOVAL_SCRIPT"
#!/bin/sh
# RAR ($RAR_VERSION) removal script
#
# Note: It must be run with the same permissions as the install
RAR_REMOVE_FAIL=0
chkdel () {
"\$@" || RAR_REMOVE_FAIL=1
}
chkdel rm -v '$RAR_BIN_DIR/rar'
chkdel rm -v '$RAR_BIN_DIR/unrar'
chkdel rm -v '$RAR_SFX_PATH'
chkdel rm -rv '$RAR_DOC_DIR'
[ -d '$RAR_NON_NATIVE_DIR/bin' ] && chkdel rm -rv '$RAR_NON_NATIVE_DIR/bin'
# The runtime libs are good for multiple versions, leave them on upgrade
if [ -z "\${RAR_UPGRADE:-}" ] && [ -d '$RAR_NON_NATIVE_DIR/lib' ]; then
chkdel rm -rv '$RAR_NON_NATIVE_DIR'
fi
# This is a config file. It might have edits
[ -e '$RAR_ORDER_PATH' ] && echo 'Warning: Not removing solid order list: $RAR_ORDER_PATH' >&2
# The license key might not be backed up
[ -e '$RAR_KEY_PATH' ] && echo 'Warning: Not removing license key: $RAR_KEY_PATH' >&2
# Leave the install/upgrade script to allow for reinstall
[ -e '$RAR_UPGRADE_SCRIPT' ] && echo 'Warning: Not removing upgrade script: $RAR_UPGRADE_SCRIPT' >&2
# Delete the system config directory /etc/rar, only for system wide installs and only if empty
# (not super important, so no need to check it worked)
if [ '${RAR_ORDER_PATH%/*}' = '/etc/rar' ]; then
find '${RAR_ORDER_PATH%/*}' -maxdepth 0 -empty -exec rmdir -v {} \;
fi
if [ "\$RAR_REMOVE_FAIL" = 0 ]; then
rm "\$0"
else
echo "Some files could not be removed; Retaining: '\$0'" >&2
exit 1
fi
UNINSTALL
chmod 755 "$RAR_REMOVAL_SCRIPT"
# Summary message to the user
cat <<-MSG
RAR ($RAR_VERSION) installed successfully!
RAR/unRAR ($MODE_PRETTY): $RAR_BIN_DIR/{rar,unrar}
MSG
if [ "$MODE" != "native" ]; then
echo "x64 Binaries (+Runtime libs): $RAR_NON_NATIVE_DIR"
fi
cat <<-MSG
Documentation: $RAR_DOC_DIR
Self-extractor: $RAR_SFX_PATH
File order list (for solid archiving): $RAR_ORDER_PATH
MSG
if [ -e "$RAR_KEY_PATH" ]; then
cat <<-MSG
License key: $RAR_KEY_PATH
MSG
else
cat <<-MSG
Remember:
* Install your rar license file to: $RAR_KEY_PATH
MSG
fi
cat <<-MSG
Update: $RAR_UPGRADE_SCRIPT
Uninstall: $RAR_REMOVAL_SCRIPT
MSG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment