--- /dev/null
+#!/usr/bin/env bash
+set -euo pipefail
+
+source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+build_dir="${WINUAE_DEB_BUILD_DIR:-/tmp/winuae_deb_build}"
+build_type="${WINUAE_DEB_BUILD_TYPE:-RelWithDebInfo}"
+jobs="${WINUAE_DEB_JOBS:-}"
+cmake_args=()
+
+usage() {
+ cat <<EOF
+Usage: $(basename "$0") [options] [-- <cmake-args>]
+
+Options:
+ --build-dir DIR CMake build directory (default: ${build_dir})
+ --build-type TYPE CMake build type (default: ${build_type})
+ --jobs N Parallel build jobs (default: detected CPU count)
+ -h, --help Show this help
+
+Extra arguments after -- are passed to the CMake configure step.
+EOF
+}
+
+while (($#)); do
+ case "$1" in
+ --build-dir)
+ if (($# < 2)); then
+ echo "error: --build-dir requires a directory" >&2
+ exit 2
+ fi
+ build_dir="$2"
+ shift 2
+ ;;
+ --build-type)
+ if (($# < 2)); then
+ echo "error: --build-type requires a value" >&2
+ exit 2
+ fi
+ build_type="$2"
+ shift 2
+ ;;
+ --jobs|-j)
+ if (($# < 2)); then
+ echo "error: --jobs requires a value" >&2
+ exit 2
+ fi
+ jobs="$2"
+ shift 2
+ ;;
+ --help|-h)
+ usage
+ exit 0
+ ;;
+ --)
+ shift
+ cmake_args+=("$@")
+ break
+ ;;
+ *)
+ echo "error: unknown option: $1" >&2
+ usage >&2
+ exit 2
+ ;;
+ esac
+done
+
+if [ "$(uname -s)" != "Linux" ]; then
+ echo "error: Debian packages can only be built on Linux" >&2
+ exit 1
+fi
+
+for tool in cmake cpack dpkg-deb dpkg-shlibdeps; do
+ if ! command -v "${tool}" >/dev/null 2>&1; then
+ echo "error: required tool not found: ${tool}" >&2
+ exit 1
+ fi
+done
+
+if [ -z "${jobs}" ]; then
+ jobs="$(getconf _NPROCESSORS_ONLN 2>/dev/null || printf '1')"
+fi
+
+cmake -S "${source_dir}" -B "${build_dir}" \
+ -DCMAKE_BUILD_TYPE="${build_type}" \
+ "${cmake_args[@]}"
+
+cmake --build "${build_dir}" \
+ --target winuae_unix_linux_package_metadata_check
+cmake --build "${build_dir}" --target package --parallel "${jobs}"
+
+mapfile -t debs < <(
+ find "${build_dir}" -maxdepth 1 -type f -name '*.deb' -printf '%T@ %p\n' |
+ sort -nr |
+ cut -d' ' -f2-
+)
+if ((${#debs[@]} == 0)); then
+ echo "error: package build completed but no .deb was found" >&2
+ echo "error: checked ${build_dir}" >&2
+ exit 1
+fi
+
+echo
+echo "Built Debian package:"
+ppc_qemu_enabled=false
+if grep -Eq '^WINUAE_UNIX_WITH_PPC_QEMU:BOOL=(ON|TRUE|1)$' \
+ "${build_dir}/CMakeCache.txt"; then
+ ppc_qemu_enabled=true
+fi
+for deb in "${debs[@]}"; do
+ echo " ${deb}"
+ dpkg-deb --field "${deb}" Package Version Architecture Depends
+
+ contents="$(dpkg-deb --contents "${deb}")"
+ if ! grep -Eq ' \./usr/bin/winuae$' <<<"${contents}"; then
+ echo "error: package does not contain /usr/bin/winuae" >&2
+ exit 1
+ fi
+ if grep -Eq ' \./usr/bin/winuae_unix$' <<<"${contents}"; then
+ echo "error: package should not install /usr/bin/winuae_unix" >&2
+ exit 1
+ fi
+ if [[ "${ppc_qemu_enabled}" == true ]]; then
+ if ! grep -Eq ' \./usr/lib.*/winuae/plugins/qemu-uae\.so$' <<<"${contents}"; then
+ echo "error: package does not contain qemu-uae.so" >&2
+ exit 1
+ fi
+ fi
+done
--- /dev/null
+#!/bin/sh
+set -eu
+
+if [ "$#" -ne 4 ]; then
+ echo "usage: $0 <target-dir> <sdk-url> <sdk-version> <sha256>" >&2
+ exit 2
+fi
+
+target_dir=$1
+sdk_url=$2
+sdk_version=$3
+sdk_sha256=$4
+
+if [ -f "$target_dir/C/7z/7zVersion.h" ] ||
+ [ -f "$target_dir/7z/7zVersion.h" ]; then
+ exit 0
+fi
+
+cache_parent=$(dirname "$target_dir")
+mkdir -p "$cache_parent"
+
+tmp_dir=$(mktemp -d "$cache_parent/.fetch-$sdk_version.XXXXXX")
+cleanup()
+{
+ rm -rf "$tmp_dir"
+}
+trap cleanup EXIT HUP INT TERM
+
+archive_path="$tmp_dir/lzma-sdk.7z"
+extract_dir="$tmp_dir/extract"
+mkdir -p "$extract_dir"
+
+if command -v curl >/dev/null 2>&1; then
+ curl -fL "$sdk_url" -o "$archive_path"
+elif command -v wget >/dev/null 2>&1; then
+ wget -O "$archive_path" "$sdk_url"
+else
+ echo "curl or wget is required to fetch $sdk_url" >&2
+ exit 1
+fi
+
+if [ -n "$sdk_sha256" ]; then
+ if command -v sha256sum >/dev/null 2>&1; then
+ archive_sha256=$(sha256sum "$archive_path" | awk '{print $1}')
+ elif command -v shasum >/dev/null 2>&1; then
+ archive_sha256=$(shasum -a 256 "$archive_path" | awk '{print $1}')
+ else
+ echo "sha256sum or shasum is required to verify $sdk_url" >&2
+ exit 1
+ fi
+ if [ "$archive_sha256" != "$sdk_sha256" ]; then
+ echo "downloaded SDK checksum mismatch for $sdk_url" >&2
+ echo "expected: $sdk_sha256" >&2
+ echo "actual: $archive_sha256" >&2
+ exit 1
+ fi
+fi
+
+extract_archive()
+{
+ if command -v cmake >/dev/null 2>&1; then
+ if (cd "$extract_dir" && cmake -E tar xf "$archive_path")
+ then
+ return 0
+ fi
+ fi
+ if command -v 7zz >/dev/null 2>&1; then
+ if 7zz x -y "-o$extract_dir" "$archive_path"; then
+ return 0
+ fi
+ fi
+ if command -v 7z >/dev/null 2>&1; then
+ if 7z x -y "-o$extract_dir" "$archive_path"; then
+ return 0
+ fi
+ fi
+ if command -v 7za >/dev/null 2>&1; then
+ if 7za x -y "-o$extract_dir" "$archive_path"; then
+ return 0
+ fi
+ fi
+ if command -v bsdtar >/dev/null 2>&1; then
+ if (cd "$extract_dir" && bsdtar -xf "$archive_path"); then
+ return 0
+ fi
+ fi
+ return 1
+}
+
+if ! extract_archive; then
+ echo "could not extract $archive_path; install cmake, 7zz, 7z, 7za, or bsdtar" >&2
+ exit 1
+fi
+
+version_header=
+for candidate in \
+ "$extract_dir/C/7z/7zVersion.h" \
+ "$extract_dir/C/7zVersion.h" \
+ "$extract_dir/7z/7zVersion.h" \
+ "$extract_dir/7zVersion.h"
+do
+ if [ -f "$candidate" ]; then
+ version_header=$candidate
+ break
+ fi
+done
+
+if [ -z "$version_header" ]; then
+ version_header=$(find "$extract_dir" -path '*/C/7z/7zVersion.h' -print -quit)
+fi
+if [ -z "$version_header" ]; then
+ version_header=$(find "$extract_dir" -path '*/C/7zVersion.h' -print -quit)
+fi
+if [ -z "$version_header" ]; then
+ version_header=$(find "$extract_dir" -path '*/7z/7zVersion.h' -print -quit)
+fi
+if [ -z "$version_header" ]; then
+ version_header=$(find "$extract_dir" -path '*/7zVersion.h' -print -quit)
+fi
+if [ -z "$version_header" ]; then
+ echo "downloaded SDK does not contain 7z/7zVersion.h" >&2
+ exit 1
+fi
+
+if ! grep -F "MY_VERSION \"$sdk_version\"" "$version_header" >/dev/null; then
+ echo "downloaded SDK is not version $sdk_version: $version_header" >&2
+ exit 1
+fi
+
+case "$version_header" in
+ */C/7z/7zVersion.h)
+ sdk_root=${version_header%/C/7z/7zVersion.h}
+ ;;
+ */C/7zVersion.h)
+ sdk_root=${version_header%/C/7zVersion.h}
+ ;;
+ */7z/7zVersion.h)
+ sdk_root=${version_header%/7z/7zVersion.h}
+ ;;
+ */7zVersion.h)
+ sdk_root=${version_header%/7zVersion.h}
+ ;;
+ *)
+ echo "unexpected SDK layout for $version_header" >&2
+ exit 1
+ ;;
+esac
+
+if [ -f "$sdk_root/C/7zVersion.h" ]; then
+ mkdir -p "$sdk_root/C/7z"
+ find "$sdk_root/C" -maxdepth 1 -type f \
+ \( -name '*.c' -o -name '*.h' -o -name '*.rc' \) \
+ -exec mv {} "$sdk_root/C/7z/" \;
+elif [ -f "$sdk_root/7zVersion.h" ]; then
+ mkdir -p "$sdk_root/7z"
+ find "$sdk_root" -maxdepth 1 -type f \
+ \( -name '*.c' -o -name '*.h' -o -name '*.rc' \) \
+ -exec mv {} "$sdk_root/7z/" \;
+fi
+
+if [ ! -f "$sdk_root/C/7z/7zVersion.h" ] &&
+ [ ! -f "$sdk_root/7z/7zVersion.h" ]; then
+ echo "could not normalize SDK layout under $sdk_root" >&2
+ exit 1
+fi
+
+target_tmp="$target_dir.tmp.$$"
+rm -rf "$target_tmp"
+mv "$sdk_root" "$target_tmp"
+rm -rf "$target_dir"
+mv "$target_tmp" "$target_dir"
--- /dev/null
+#!/bin/sh
+set -eu
+
+if [ "$#" -ne 1 ]; then
+ echo "usage: $0 <qemu-uae-plugin>" >&2
+ exit 2
+fi
+
+plugin=$1
+
+if [ ! -f "$plugin" ]; then
+ echo "error: Unix PPC support is enabled, but no qemu-uae.so" \
+ "plugin is available for packaging." >&2
+ echo "error: expected plugin: $plugin" >&2
+ echo "error: set WINUAE_QEMU_UAE_PLUGIN_FILE or build the" \
+ "winuae_unix_qemu_uae_plugin target." >&2
+ exit 1
+fi
--- /dev/null
+#!/usr/bin/env bash
+set -euo pipefail
+
+source_dir="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
+
+desktop="${source_dir}/od-unix/share/applications/net.winuae.WinUAE.desktop"
+mime="${source_dir}/od-unix/share/mime/packages/net.winuae.WinUAE.xml"
+icon="${source_dir}/od-win32/resources/amiga.png"
+cmake="${source_dir}/CMakeLists.txt"
+readme="${source_dir}/README_unix.md"
+deb_builder="${source_dir}/tools/debian-build-package.sh"
+deb_postinst="${source_dir}/packaging/debian/postinst"
+deb_postrm="${source_dir}/packaging/debian/postrm"
+
+require_file() {
+ local path="$1"
+ local label="$2"
+ if [[ ! -f "${path}" ]]; then
+ echo "error: missing ${label}: ${path}" >&2
+ exit 1
+ fi
+}
+
+require_match() {
+ local pattern="$1"
+ local path="$2"
+ local label="$3"
+ if ! grep -Eq "${pattern}" "${path}"; then
+ echo "error: ${label} not found in ${path}" >&2
+ exit 1
+ fi
+}
+
+require_file "${desktop}" "desktop entry"
+require_file "${mime}" "MIME package"
+require_file "${icon}" "Linux icon source"
+require_file "${cmake}" "CMake package rules"
+require_file "${readme}" "README package documentation"
+require_file "${deb_builder}" "Debian package builder"
+require_file "${deb_postinst}" "Debian postinst control script"
+require_file "${deb_postrm}" "Debian postrm control script"
+
+require_match '^\[Desktop Entry\]$' "${desktop}" "desktop header"
+require_match '^Type=Application$' "${desktop}" "desktop application type"
+require_match '^Name=WinUAE$' "${desktop}" "desktop name"
+require_match '^Exec=winuae %f$' "${desktop}" "desktop exec"
+require_match '^Icon=winuae$' "${desktop}" "desktop icon"
+require_match '^Categories=.*(^|;)Emulator(;|$)' "${desktop}" "desktop category"
+require_match '^MimeType=application/x-winuae-config;$' "${desktop}" "desktop MIME type"
+
+require_match '<mime-type type="application/x-winuae-config">' "${mime}" "MIME type"
+require_match '<glob pattern="\*\.uae"/>' "${mime}" "MIME glob"
+
+if ! file "${icon}" | grep -q 'PNG image data'; then
+ echo "error: Linux icon source is not a PNG: ${icon}" >&2
+ exit 1
+fi
+
+require_match 'install\(PROGRAMS "\$<TARGET_FILE:winuae_unix>"' "${cmake}" "Linux executable install rule"
+require_match 'RENAME winuae' "${cmake}" "Linux executable install name"
+require_match 'WINUAE_UNIX_INSTALL_PLUGINDIR_RELATIVE' "${cmake}" "Linux plugin install directory"
+require_match 'WINUAE_QEMU_UAE_PLUGIN_FILE' "${cmake}" "prebuilt QEMU-UAE plugin option"
+require_match 'winuae_unix_qemu_uae_package_check' "${cmake}" "QEMU-UAE package requirement"
+require_match 'install\(FILES "\$\{WINUAE_QEMU_UAE_PLUGIN_PATH\}"' "${cmake}" "QEMU-UAE plugin install rule"
+require_match 'od-unix/share/applications/net\.winuae\.WinUAE\.desktop' "${cmake}" "desktop install rule"
+require_match 'od-unix/share/mime/packages/net\.winuae\.WinUAE\.xml' "${cmake}" "MIME install rule"
+require_match 'icons/hicolor/256x256/apps' "${cmake}" "application icon install rule"
+require_match 'icons/hicolor/256x256/mimetypes' "${cmake}" "MIME icon install rule"
+require_match 'set\(CPACK_GENERATOR "TGZ"\)' "${cmake}" "CPack TGZ generator"
+require_match 'list\(APPEND CPACK_GENERATOR "DEB"\)' "${cmake}" "CPack DEB generator"
+require_match 'CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON' "${cmake}" "CPack Debian shlibdeps"
+require_match 'CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA' "${cmake}" "CPack Debian control scripts"
+require_match 'packaging/debian/postinst' "${cmake}" "Debian postinst registration"
+require_match 'packaging/debian/postrm' "${cmake}" "Debian postrm registration"
+require_match 'add_dependencies\(package winuae_unix_qemu_uae_plugin\)' "${cmake}" "package plugin dependency"
+
+require_match 'cmake --install /tmp/winuae_cmake_build --prefix /opt/winuae' "${readme}" "Linux install instructions"
+require_match 'cmake --build /tmp/winuae_cmake_build --target package' "${readme}" "Linux package instructions"
+require_match 'tools/debian-build-package.sh' "${readme}" "Debian package helper instructions"
+require_match 'installs the emulator as `winuae`' "${readme}" "Debian command name documentation"
+require_match 'qemu-uae\.so' "${readme}" "QEMU-UAE package documentation"
+require_match 'WINUAE_UNIX_WITH_PPC_QEMU:BOOL' "${deb_builder}" "Debian plugin requirement"
+require_match '/usr/bin/winuae' "${deb_builder}" "Debian installed binary check"
+require_match 'package does not contain qemu-uae\.so' "${deb_builder}" "Debian plugin contents check"
+
+echo "verified Linux package metadata"