Skip to content

Instantly share code, notes, and snippets.

@rezzafr33
Last active May 14, 2025 05:14
Show Gist options
  • Save rezzafr33/3c6afe73c2356353478ab8c4f02c678d to your computer and use it in GitHub Desktop.
Save rezzafr33/3c6afe73c2356353478ab8c4f02c678d to your computer and use it in GitHub Desktop.
Podman Setup Script for Compiling binder_linux.ko on Steam Deck

Steam Deck Binder Module Builder

Compile binder_linux.ko for Steam Deck using Podman containers.

Prerequisites

  • Steam Deck
  • Podman installed (preinstalled on Steam Deck)
  • Internet connection

Usage

./podman_compile_binder.sh [options]

Options:

Flag Description
-f Force rebuild module
-b Force rebuild container image
-bf or -fb Force rebuild both

Examples:

# Basic compilation
./podman_compile_binder.sh

# Force module rebuild
./podman_compile_binder.sh -f

# Full clean rebuild
./podman_compile_binder.sh -bf

Output

Successful builds create:

~/waydroid/module/[kernel-version]/binder_linux.ko

Loading the Module

sudo insmod ~/waydroid/module/$(uname -r)/binder_linux.ko

FAQ

Why Podman?

Podman is Steam Deck's default container tool and runs without root.

Storage Requirements

  • ~1GB for container image
  • ~100MB for build files
#!/bin/bash
set -euo pipefail
# Configuration
KERNEL_VERSION=$(uname -r)
OUTPUT_DIR="$HOME/waydroid/module/${KERNEL_VERSION}"
MODULE_PATH="${OUTPUT_DIR}/binder_linux.ko"
BASE_IMAGE="ghcr.io/steamdeckhomebrew/holo-base:latest"
PREBUILT_IMAGE="local/holo-base-prepped:latest"
MODULE_SOURCE="https://github.com/llyyr/anbox-modules"
FORCE_MODULE=false
FORCE_IMAGE=false
# Parse arguments
while getopts "fb" opt; do
case $opt in
f) FORCE_MODULE=true ;;
b) FORCE_IMAGE=true ;;
*) echo "Usage: $0 [-f] [-b]"
echo "Options:"
echo " -f Force rebuild module"
echo " -b Force rebuild container image"
exit 1 ;;
esac
done
# Create output directory
mkdir -p "${OUTPUT_DIR}"
# --- Container Image Preparation ---
echo "[INFO] Preparing container environment..."
if [[ "$FORCE_IMAGE" == true ]]; then
echo "[INFO] Forcing rebuild of pre-configured image..."
echo "[INFO] Pulling latest base image..."
if ! podman pull "$BASE_IMAGE"; then
echo "[ERROR] Failed to pull base image" >&2
exit 1
fi
podman rmi "$PREBUILT_IMAGE" 2>/dev/null || true
fi
if ! podman image exists "$PREBUILT_IMAGE" || [[ "$FORCE_IMAGE" == true ]]; then
echo "[INFO] Building pre-configured image with custom pacman.conf..."
BUILD_DIR=$(mktemp -d)
cp /etc/pacman.conf "$BUILD_DIR/"
cat > "$BUILD_DIR/Containerfile" <<EOF
FROM $BASE_IMAGE
COPY pacman.conf /etc/pacman.conf
RUN pacman -Sy --noconfirm --needed archlinux-keyring && \
pacman -Syu --noconfirm --needed && \
yes | pacman -Scc && \
rm -rf /usr/share/{doc,info,man}
EOF
if ! podman build --squash -t "$PREBUILT_IMAGE" -f "$BUILD_DIR/Containerfile" "$BUILD_DIR"; then
echo "[ERROR] Failed to build pre-configured image" >&2
rm -rf "$BUILD_DIR"
exit 1
fi
rm -rf "$BUILD_DIR"
echo "[INFO] Pre-configured image ready"
else
echo "[INFO] Using existing pre-configured image"
fi
# --- Module Existence Check ---
if [[ "$FORCE_MODULE" == false ]] && [[ -f "${MODULE_PATH}" ]]; then
echo "[INFO] Module already exists at ${MODULE_PATH}, skipping compilation."
echo "[INFO] Use -f to force module rebuild or -b to rebuild image."
exit 0
fi
# Verify output directory is writable
if [[ ! -w "${OUTPUT_DIR}" ]]; then
echo "[ERROR] Cannot write to output directory: ${OUTPUT_DIR}" >&2
exit 1
fi
# --- Module Building ---
KERNEL_PKG=$(basename /boot/vmlinuz-* | sed 's/vmlinuz-//')
HEADERS_PKG="${KERNEL_PKG}-headers"
echo "[INFO] Building module with kernel headers: ${HEADERS_PKG}"
if ! podman run --rm \
--user 0 \
--security-opt label=disable \
--cap-add=SYS_MODULE \
-v /etc/pacman.conf:/tmp/pacman.conf:ro \
-v "${OUTPUT_DIR}:/output:z" \
-v /tmp:/tmp:z \
"$PREBUILT_IMAGE" \
/bin/bash -c "
set -euo pipefail
echo '[CONTAINER] Finalizing build environment...'
# Replace pacman config
install -m644 /tmp/pacman.conf /etc/pacman.conf
# Update and install build tools
pacman -Syu --noconfirm --needed
pacman -S --noconfirm --needed base-devel git
# Install kernel headers
if ! pacman -S --noconfirm --needed ${HEADERS_PKG}; then
echo '[ERROR] Failed to install kernel headers' >&2
echo '[INFO] Available headers packages:'
pacman -Ss 'headers' || true
exit 1
fi
# Always clean previous build
rm -rf /tmp/anbox-modules 2>/dev/null || true
# Clone and build
echo '[CONTAINER] Building binder module...'
if ! git clone --depth 1 ${MODULE_SOURCE} /tmp/anbox-modules; then
echo '[ERROR] Failed to clone repository' >&2
exit 1
fi
cd /tmp/anbox-modules/binder || exit 1
if ! make; then
echo '[ERROR] Build failed - showing last 50 lines of build log:'
tail -n 50 /tmp/anbox-modules/binder/build.log 2>/dev/null || true
exit 1
fi
# Verify and copy output
if [[ -f binder_linux.ko ]]; then
install -m644 binder_linux.ko /output/
echo '[CONTAINER] Module built successfully'
else
echo '[ERROR] Module file not found after build' >&2
exit 1
fi
"; then
echo "[ERROR] Module build failed in container" >&2
exit 1
fi
# Verify output
if [[ -f "${MODULE_PATH}" ]]; then
chown "$(id -u):$(id -g)" "${MODULE_PATH}"
echo "[SUCCESS] Module built at ${MODULE_PATH}"
echo "[NOTE] Load with: sudo insmod ${MODULE_PATH}"
else
echo "[ERROR] Module was not created at ${MODULE_PATH}" >&2
exit 1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment