Steam Frame build, packaging and deployment scripts; render test
- build_scripts/steamframe/: Debian trixie (Qt 6.8) containers for the aarch64 cross build, native build and tests; toolchain; scripts to build, test (Vulkan validation layers), package (system Qt, ~3 MB) and deploy over SSH. Adapted from the vrdashboard template. - test/render/: render test for the OpenGL and Vulkan backends, driven like OverlayController (option OVRAS_BUILD_TESTS). - RPATH only $ORIGIN, without the build machine's link directories. - Ignore dist/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b22c35ae29
commit
bde675f1b8
@@ -0,0 +1,27 @@
|
||||
# CMake toolchain: cross-compile for aarch64 Linux (Steam Frame) inside
|
||||
# cross-arm64.Dockerfile (Debian multiarch). Used by container-build.sh.
|
||||
# Adapted from the vrdashboard template.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||
|
||||
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
|
||||
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
|
||||
|
||||
# Debian multiarch: target libraries live in /usr/lib/aarch64-linux-gnu;
|
||||
# headers are shared.
|
||||
set(CMAKE_LIBRARY_ARCHITECTURE aarch64-linux-gnu)
|
||||
set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
|
||||
set(ENV{PKG_CONFIG_LIBDIR} /usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig)
|
||||
|
||||
# Qt 6 cross builds need a host Qt for its code generators (moc, rcc,
|
||||
# qmlcachegen, ...).
|
||||
set(QT_HOST_PATH /usr CACHE PATH "Host Qt prefix")
|
||||
set(QT_HOST_PATH_CMAKE_DIR /usr/lib/x86_64-linux-gnu/cmake CACHE PATH "Host Qt CMake dir")
|
||||
set(CMAKE_PREFIX_PATH /usr/lib/aarch64-linux-gnu/cmake)
|
||||
|
||||
set(CMAKE_OBJDUMP aarch64-linux-gnu-objdump)
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
# Builds OVRAS for the Steam Frame inside a Debian container (Qt 6.8, the
|
||||
# series of the Frame's system Qt). Result: build/steamframe-<mode>/Release/,
|
||||
# packaged by package-release.sh. Adapted from the vrdashboard template.
|
||||
#
|
||||
# build_scripts/steamframe/container-build.sh cross x86_64 host -> aarch64
|
||||
# build_scripts/steamframe/container-build.sh native for the host's own
|
||||
# architecture (on the Frame: native arm64)
|
||||
# build_scripts/steamframe/container-build.sh <mode> shell
|
||||
# interactive shell in that container
|
||||
#
|
||||
# Uses podman if available, else docker (override with CONTAINER_ENGINE).
|
||||
set -euo pipefail
|
||||
|
||||
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
root="$(cd "$here/../.." && pwd)"
|
||||
mode="${1:-}"
|
||||
case "$mode" in
|
||||
cross) dockerfile=cross-arm64.Dockerfile
|
||||
toolchain="-DCMAKE_TOOLCHAIN_FILE=build_scripts/steamframe/aarch64-linux-gnu.cmake" ;;
|
||||
native) dockerfile=native.Dockerfile; toolchain="" ;;
|
||||
*) echo "usage: $0 cross|native [shell]" >&2; exit 2 ;;
|
||||
esac
|
||||
image="ovras-steamframe-${dockerfile%.Dockerfile}"
|
||||
engine="${CONTAINER_ENGINE:-$(command -v podman || command -v docker)}"
|
||||
build="build/steamframe-$mode"
|
||||
|
||||
"$engine" build -q -t "$image" -f "$here/$dockerfile" "$here" >/dev/null
|
||||
|
||||
# Run as the calling user, so the build tree isn't owned by root.
|
||||
run=("$engine" run --rm -v "$root:$root:z" -w "$root")
|
||||
if [[ "$(basename "$engine")" == docker ]]; then
|
||||
run+=(--user "$(id -u):$(id -g)")
|
||||
else
|
||||
run+=(--userns=keep-id)
|
||||
fi
|
||||
[[ -t 0 ]] && run+=(-it)
|
||||
|
||||
if [[ "${2:-}" == shell ]]; then
|
||||
exec "${run[@]}" "$image" bash
|
||||
fi
|
||||
|
||||
# OVRAS_STEAM_FRAME: Frame capabilities and defaults
|
||||
# (src/utils/platform_capabilities.h).
|
||||
"${run[@]}" "$image" bash -c "
|
||||
set -e
|
||||
cmake -S . -B $build -G Ninja -DCMAKE_BUILD_TYPE=Release \
|
||||
-DOVRAS_STEAM_FRAME=ON $toolchain
|
||||
cmake --build $build
|
||||
"
|
||||
echo "Built: $root/$build/Release"
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# Builds and runs the tests (OVRAS_BUILD_TESTS) in a Debian container with
|
||||
# both render backends, Vulkan with the Khronos validation layers. Fails on any
|
||||
# validation message. Adapted from the vrdashboard template.
|
||||
#
|
||||
# build_scripts/steamframe/container-test.sh GPU via /dev/dri if
|
||||
# available, else software
|
||||
# VK_DRIVER=lvp build_scripts/steamframe/container-test.sh
|
||||
# force lavapipe (software)
|
||||
set -euo pipefail
|
||||
|
||||
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
root="$(cd "$here/../.." && pwd)"
|
||||
engine="${CONTAINER_ENGINE:-$(command -v podman || command -v docker)}"
|
||||
"$engine" build -q -t ovras-steamframe-native -f "$here/native.Dockerfile" "$here" >/dev/null
|
||||
"$engine" build -q -t ovras-steamframe-test -f "$here/test.Dockerfile" "$here" >/dev/null
|
||||
|
||||
run=("$engine" run --rm -v "$root:$root:z" -w "$root" -e HOME=/tmp -e "VK_DRIVER=${VK_DRIVER:-}")
|
||||
if [[ "$(basename "$engine")" == docker ]]; then
|
||||
run+=(--user "$(id -u):$(id -g)")
|
||||
else
|
||||
run+=(--userns=keep-id)
|
||||
fi
|
||||
[[ -e /dev/dri/renderD128 ]] && run+=(--device /dev/dri/renderD128)
|
||||
|
||||
"${run[@]}" ovras-steamframe-test bash -c '
|
||||
set -e
|
||||
build=build/steamframe-test
|
||||
cmake -S . -B $build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DOVRAS_BUILD_TESTS=ON >/dev/null
|
||||
cmake --build $build --target tst_render
|
||||
if [[ -n "$VK_DRIVER" ]]; then export VK_DRIVER_FILES=/usr/share/vulkan/icd.d/${VK_DRIVER}_icd.json; fi
|
||||
vulkaninfo --summary 2>/dev/null | grep -m1 deviceName || true
|
||||
Xvfb :99 >/dev/null 2>&1 &
|
||||
sleep 1
|
||||
export DISPLAY=:99 OVRAS_VULKAN_VALIDATION=1
|
||||
ctest --test-dir $build --output-on-failure -V > $build/ctest.log 2>&1 \
|
||||
|| { tail -40 $build/ctest.log; exit 1; }
|
||||
grep -E "tests passed|Test +#|Totals" $build/ctest.log
|
||||
# A skipped test (no GPU context) must not count as passed.
|
||||
if grep -q "SKIP" $build/ctest.log; then
|
||||
echo "Tests were skipped (see $build/ctest.log)"; exit 1
|
||||
fi
|
||||
messages=$(grep -oE "(VUID|UNASSIGNED)-[A-Za-z0-9_.-]+" $build/ctest.log | sort | uniq -c || true)
|
||||
if [[ -n "$messages" ]]; then
|
||||
echo "Vulkan validation messages (see $build/ctest.log):"
|
||||
echo "$messages"
|
||||
exit 1
|
||||
fi
|
||||
echo "No Vulkan validation messages."
|
||||
'
|
||||
@@ -0,0 +1,20 @@
|
||||
# Cross-compilation environment for the Steam Frame (aarch64), from an x86_64
|
||||
# host via Debian multiarch: the compiler and Qt's code generators (moc, rcc,
|
||||
# qmlcachegen) run natively as amd64 builds, the target libraries are the
|
||||
# arm64 builds. Debian trixie ships Qt 6.8, the series of the Frame's system
|
||||
# Qt (SteamOS holo 0.4.3: 6.8.0). Adapted from the vrdashboard template.
|
||||
FROM debian:trixie
|
||||
|
||||
ENV LANG=C.UTF-8
|
||||
|
||||
RUN dpkg --add-architecture arm64 \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates cmake ninja-build pkgconf file \
|
||||
g++-aarch64-linux-gnu binutils-aarch64-linux-gnu \
|
||||
qt6-base-dev qt6-base-dev-tools qt6-declarative-dev qt6-declarative-dev-tools \
|
||||
qt6-base-dev:arm64 qt6-declarative-dev:arm64 qt6-multimedia-dev:arm64 \
|
||||
qt6-websockets-dev:arm64 qt6-svg-dev:arm64 \
|
||||
libgl-dev:arm64 libegl-dev:arm64 libvulkan-dev:arm64 libxkbcommon-dev:arm64 \
|
||||
libx11-dev:arm64 libxt-dev:arm64 libxtst-dev:arm64 libpulse-dev:arm64 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copies the newest package (package-release.sh) to the Steam Frame over SSH
|
||||
# and runs its install.sh there (registers with SteamVR and starts it; an
|
||||
# existing installation in the same place is updated). SteamVR must be running
|
||||
# on the Frame. Adapted from the vrdashboard template.
|
||||
#
|
||||
# build_scripts/steamframe/deploy-to-frame.sh <ssh-target> [package-dir] [remote-dir]
|
||||
# e.g. build_scripts/steamframe/deploy-to-frame.sh steamos@frame
|
||||
#
|
||||
# remote-dir defaults to "AdvancedSettings" in the remote home directory.
|
||||
set -euo pipefail
|
||||
|
||||
target="${1:?usage: $0 <ssh-target> [package-dir] [remote-dir]}"
|
||||
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
package="${2:-$(ls -dt "$root"/dist/AdvancedSettings-*-linux-arm64 2>/dev/null | head -1)}"
|
||||
[[ -n "$package" && -x "$package/install.sh" ]] || {
|
||||
echo "No package found (run build_scripts/steamframe/package-release.sh first)" >&2; exit 1; }
|
||||
# Without the version: updates go to the same place and replace the old one.
|
||||
remote="${3:-AdvancedSettings}"
|
||||
|
||||
# Keep the log of earlier runs on the Frame.
|
||||
rsync -a --delete --exclude AdvancedSettings.log "$package/" "$target:$remote/"
|
||||
ssh "$target" "\$HOME/$remote/install.sh"
|
||||
echo "Installed $(basename "$package") to $target:~/$remote"
|
||||
@@ -0,0 +1,19 @@
|
||||
# Native build environment (any architecture). On x86_64 it is the base of the
|
||||
# test container (test.Dockerfile); on the Steam Frame itself (aarch64, e.g.
|
||||
# with podman) it builds the same package as the cross build. Debian trixie
|
||||
# ships Qt 6.8, the series of the Frame's system Qt. Adapted from the
|
||||
# vrdashboard template.
|
||||
FROM debian:trixie
|
||||
|
||||
ENV LANG=C.UTF-8
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates cmake ninja-build pkgconf file g++ \
|
||||
qt6-base-dev qt6-base-dev-tools qt6-declarative-dev qt6-declarative-dev-tools \
|
||||
qt6-multimedia-dev qt6-websockets-dev qt6-svg-dev \
|
||||
libgl-dev libegl-dev libvulkan-dev libxkbcommon-dev \
|
||||
libx11-dev libxt-dev libxtst-dev libpulse-dev \
|
||||
qml6-module-qtquick qml6-module-qtqml-workerscript qml6-module-qtquick-window \
|
||||
qt6-qpa-plugins \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
Executable
+93
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env bash
|
||||
# Builds OVRAS for the Steam Frame (aarch64) and packages it:
|
||||
# dist/AdvancedSettings-<version>-linux-arm64/ (+ .tar.gz)
|
||||
# The package uses SteamOS's own Qt (no Qt bundled). It contains the program
|
||||
# folder as OVRAS expects it (binary, libopenvr_api.so, manifests, res/) plus
|
||||
# install.sh, uninstall.sh, run.sh and README.txt. Adapted from the
|
||||
# vrdashboard template.
|
||||
#
|
||||
# build_scripts/steamframe/package-release.sh [--no-build]
|
||||
set -euo pipefail
|
||||
|
||||
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
root="$(cd "$here/../.." && pwd)"
|
||||
build=1
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--no-build) build=0 ;;
|
||||
*) echo "usage: $0 [--no-build]" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
# On the Frame itself build natively, elsewhere cross-compile.
|
||||
if [[ "$(uname -m)" == aarch64 ]]; then mode=native; else mode=cross; fi
|
||||
|
||||
(( build )) && "$here/container-build.sh" "$mode"
|
||||
|
||||
exe=AdvancedSettings_app
|
||||
bin="$root/build/steamframe-$mode/Release"
|
||||
version="$(sed -n 's/^CMAKE_PROJECT_VERSION:[A-Z]*=//p' "$root/build/steamframe-$mode/CMakeCache.txt")"
|
||||
[[ "$(file -b "$bin/$exe")" == *aarch64* ]] || { echo "$bin/$exe is not an aarch64 build" >&2; exit 1; }
|
||||
|
||||
package="AdvancedSettings-$version-linux-arm64"
|
||||
out="$root/dist/$package"
|
||||
rm -rf "$out" "$out.tar.gz"
|
||||
mkdir -p "$out"
|
||||
cp -a "$bin/." "$out/"
|
||||
|
||||
# The scripts start the program from the package folder: OVRAS writes its log
|
||||
# (AdvancedSettings.log) to the working directory. Process names are cut to
|
||||
# 15 characters, so running instances are found by command line.
|
||||
cat > "$out/install.sh" <<EOF
|
||||
#!/bin/sh
|
||||
# Installs or updates OVR Advanced Settings: registers it with SteamVR (starts
|
||||
# automatically with SteamVR from now on) and starts it now. SteamVR must be
|
||||
# running. Works over SSH.
|
||||
cd "\$(dirname "\$0")" || exit 1
|
||||
# An update replaces the files of a running instance: stop it first.
|
||||
pkill -f "/$exe( |\\\$)" 2>/dev/null && sleep 1
|
||||
./$exe --force-install-manifest || exit 1
|
||||
# Start now. Over SSH there is no display; Qt needs one even for off-screen
|
||||
# rendering, so use the Frame's (:0).
|
||||
DISPLAY="\${DISPLAY:-:0}" nohup ./$exe >/dev/null 2>&1 &
|
||||
echo "Installed and started."
|
||||
EOF
|
||||
|
||||
cat > "$out/uninstall.sh" <<EOF
|
||||
#!/bin/sh
|
||||
# Unregisters OVR Advanced Settings from SteamVR and stops it. The folder can
|
||||
# be deleted afterwards.
|
||||
cd "\$(dirname "\$0")" || exit 1
|
||||
pkill -f "/$exe( |\\\$)" 2>/dev/null
|
||||
exec ./$exe --force-remove-manifest
|
||||
EOF
|
||||
|
||||
cat > "$out/run.sh" <<EOF
|
||||
#!/bin/sh
|
||||
# Restarts OVR Advanced Settings with the given graphics API, for testing:
|
||||
# ./run.sh [opengl|vulkan] (default: opengl)
|
||||
cd "\$(dirname "\$0")" || exit 1
|
||||
pkill -f "/$exe( |\\\$)" 2>/dev/null && sleep 1
|
||||
DISPLAY="\${DISPLAY:-:0}" nohup ./$exe --graphics-api "\${1:-opengl}" >/dev/null 2>&1 &
|
||||
echo "Started with \${1:-opengl}; log: \$(pwd)/AdvancedSettings.log"
|
||||
EOF
|
||||
chmod +x "$out/install.sh" "$out/uninstall.sh" "$out/run.sh"
|
||||
|
||||
cat > "$out/README.txt" <<EOF
|
||||
OVR Advanced Settings $version for the Steam Frame (SteamOS, aarch64)
|
||||
|
||||
Uses the system's Qt (SteamOS: Qt 6.8 or newer).
|
||||
|
||||
Install / update: ./install.sh (SteamVR must be running)
|
||||
SteamVR remembers this folder's location: after moving it,
|
||||
run ./install.sh again.
|
||||
Uninstall: ./uninstall.sh
|
||||
Test a graphics API: ./run.sh opengl | ./run.sh vulkan
|
||||
Log: AdvancedSettings.log in the working directory (this folder
|
||||
when started by the scripts)
|
||||
|
||||
License: GPL-3.0 (LICENSE); OpenVR: LICENSE-VALVE.
|
||||
EOF
|
||||
|
||||
tar -C "$root/dist" -czf "$out.tar.gz" "$package"
|
||||
echo "Release folder: $out"
|
||||
echo "Archive: $out.tar.gz ($(du -h "$out.tar.gz" | cut -f1))"
|
||||
@@ -0,0 +1,10 @@
|
||||
# Test environment on top of native.Dockerfile: Mesa Vulkan/GL drivers (incl.
|
||||
# the lavapipe software rasterizer), the Khronos validation layers and Xvfb.
|
||||
# See container-test.sh. Adapted from the vrdashboard template.
|
||||
FROM ovras-steamframe-native
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
mesa-vulkan-drivers vulkan-validationlayers vulkan-tools libgl1-mesa-dri \
|
||||
xvfb xauth \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
Reference in New Issue
Block a user