Example: Advanced Build Techniques

These examples showcase more advanced features and workflows, such as running builds as root or using custom viewers for file inspection.

Building as Root with sync-asroot

Normally, aur-build runs as a regular user and uses sudo (or a similar tool) to elevate privileges for specific tasks like installing dependencies or updating the local repository.

The sync-asroot script demonstrates an alternative approach: running the entire build process as root and dropping privileges for tasks that should be unprivileged, like running makepkg or gpg.

This is achieved by setting environment variables that replace the default commands with versions that use runuser:

  • AUR_MAKEPKG="runuser -u <user> -- makepkg"
  • AUR_GPG="runuser -u <user> -- gpg"
  • AUR_REPO_ADD="runuser -u <user> -- repo-add"

Warning: Building with makechrootpkg as root gives the build process unfettered access to the host system, regardless of how the build user is configured. Exercise caution with this method.

sync-asroot Script

#!/bin/bash
# run as: `sudo sync-asroot ...`
[[ -v AUR_DEBUG ]] && set -o xtrace
SUDO_HOME=$(eval echo "~$SUDO_USER")
XDG_CACHE_HOME=${XDG_CACHE_HOME:-$SUDO_HOME/.cache}
AURDEST=${AURDEST:-$XDG_CACHE_HOME/aurutils/sync}
argv0=sync-asroot

# default options
build_args=(-LR --chroot) sync_args=() keep_going=1

# colors (for build summary)
source /usr/share/makepkg/util/message.sh

if [[ ! -v NO_COLOR ]] && [[ ! -v AUR_DEBUG ]]; then
    [[ -t 2 ]] && colorize
fi

# option parsing
unset build_user
while getopts :U:d:k:fSuN OPT; do
    case $OPT in
        d) build_args+=(-d "$OPTARG"); sync_args+=(-d "$OPTARG") ;;
        f) build_args+=(-f "$OPTARG") ;;
        S) build_args+=(-S) ;;
        U) build_user=$OPTARG ;;
        k) keep_going=$OPTARG ;;
        u) sync_args+=(-u) ;;
        N) sync_args+=(--no-ver) ;;
    esac
done
shift $(( OPTIND-1 ))

# 1. define unprivileged commands ------------------------------------------------->
build_user=${build_user:-${SUDO_USER:-$USER}}
build_args+=(-U "$build_user")

build_env=(AUR_MAKEPKG="runuser -u $build_user -- makepkg"
           AUR_GPG="runuser -u $build_user -- gpg"
           AUR_REPO_ADD="runuser -u $build_user -- repo-add"
           AUR_BUILD_PKGLIST="runuser -u $build_user -- aur build--pkglist")

# 2. retrieve sources ------------------------------------------------------------->
ninja_dir=$(runuser -u "$build_user" -- mktemp -d) || exit
trap 'rm -rf "$ninja_dir"' EXIT

runuser -u "$build_user" -- \
    env AURDEST="$AURDEST" aur sync "${sync_args[@]}" "$@" --columns --save "$ninja_dir"/graph || exit 1

# 3. build queue ------------------------------------------------------------------>
if [[ -s $ninja_dir/graph ]]; then
    runuser -u "$build_user" -- aur sync--ninja "$AURDEST" <"$ninja_dir"/graph >"$ninja_dir"/build.ninja -- \
        env AUR_ASROOT=1 "${build_env[@]}" aur build "${build_args[@]}"

    env NINJA_STATUS='[%s/%t] ' ninja -C "$ninja_dir" -k "$keep_going"

    # ... (build summary continues)
fi

Custom File Viewing with view-delta

aur-view uses a file manager defined by the AUR_PAGER environment variable to inspect build files. The view-delta script is an example of a custom pager that provides a different inspection experience.

Instead of an interactive file manager, view-delta assumes you won't be editing the files. It uses modern command-line tools for a read-only review:

  1. Displays Diffs: It uses delta (or diff-so-fancy) to show colorful, side-by-side diffs for any changed files.
  2. Displays Other Files: It uses bat for syntax-highlighted output of any new or unchanged files.
  3. Confirmation Prompt: It displays a prompt at the end, allowing you to continue (by pressing Enter) or abort the build (by pressing Ctrl+D).

Usage

Set AUR_PAGER to the path of the view-delta script:

AUR_PAGER=/path/to/view-delta aur sync <package>

view-delta Script

#!/bin/bash
[[ -v AUR_DEBUG ]] && set -o xtrace
set -o errexit
shopt -s extglob

# Helper function to take complements of pkgbase arrays
filter_packages() { grep -Fxvf <(printf '%s\n' "$@") -; }

# Directory with diffs and PKGBUILD subdirs
cd "${1:-/dev/null}"
diffs=(@(*.diff|*.log))
pkgbases=(*/)
pkgbases=("${pkgbases[@]%/}")

# Show diffs in 2 panes
if [[ -f ${diffs[0]} ]]; then
    cat "${diffs[@]}" | delta --diff-so-fancy --paging=always --line-numbers --navigate

    # Remove diffs from remaining targets (new or unchanged dirs)
    mapfile -t pkgbases < <(
        printf '%s\n' "${pkgbases[@]}" | filter_packages "${diffs[@]%%.*}")
fi >&2

# Show remaining targets in a concatenated fashion
if (( ${#pkgbases[@]} )); then
    # Only print files in the git repository
    find -L "${pkgbases[@]}" -prune -exec sh -c 'git -C {} ls-files -z | env -C {} xargs -0r realpath -z' \; |
        grep -Ezv '.SRCINFO|.gitignore' | xargs -0r bat --paging=always
fi >&2

# Show an exit prompt
read -rp $'Press Return to continue or Ctrl+d to abort\n'