mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-25 14:00:41 +01:00
The container becomes an artifact instead of a recipe: the base toolbox image is pinned by digest, Python dependencies come from the committed uv.lock (uv-managed CPython, clean venv at /opt/frametop/venv, no system-site-packages), and OpenVR's header and libopenvr_api come from the same pinned public tag the Frame-side build scripts pin. The native binaries compile inside the image the same way the build.sh scripts compile them; hand tracking stays deferred as in install.sh. - ft: one wrapper for everything that runs (build, shell, run, test, update); Frame mounts (ipc=host, /run/user, /opt/steamvr) are designed behind FT_FRAME=1 until validated on the device (pack/README.md) - justfile: runner for the in-image actions (test, lint as report, check) - CI: native arm64 runner builds and pushes ghcr.io/0x1f6/frametop and runs the suites inside the built image as a smoke job; actions pinned to SHAs Validated locally (docker, aarch64): full build, all six binaries, and ./ft test green (unittest suites, check scripts, 11 pytest tests).
108 lines
6.8 KiB
Docker
108 lines
6.8 KiB
Docker
# Frametop runtime image (see pack/README.md).
|
|
#
|
|
# One image that holds everything Frametop needs: the frozen toolchain and C
|
|
# libraries, its native binaries, and its locked Python environment. A given
|
|
# image tag always behaves the same, on a PC and on the Frame.
|
|
#
|
|
# setup/dev-container.sh stays the source of truth for the package list on the
|
|
# Frame's dev container; the list below freezes the runtime-relevant subset of
|
|
# it plus the toolchain (the binaries are built in this image). Keep the two in
|
|
# sync on purpose: dev-container.sh documents *why* each package is there.
|
|
FROM registry.fedoraproject.org/fedora-toolbox:44@sha256:034cb7c472038e2d879ddc19568106a1342aa24403f0d641a0f73dda638707ad
|
|
|
|
# Toolchain (the binaries are built in here) and the libraries they link.
|
|
RUN dnf -y install --setopt=install_weak_deps=False \
|
|
gcc gcc-c++ make pkgconf-pkg-config git curl unzip just \
|
|
pipewire-devel libxkbcommon-devel libinput-devel systemd-devel dbus-devel \
|
|
libdrm-devel mesa-libgbm-devel wayland-devel vulkan-loader-devel \
|
|
vulkan-headers plasma-wayland-protocols wlroots-devel pixman-devel \
|
|
libstdc++-static glibc-static jsoncpp-devel zstd \
|
|
# Frametop Input Settings (Kirigami, PySide6) and remote desktop (krdp):
|
|
# the KDE/Qt stack has no PyPI wheels, so it stays a dnf package
|
|
python3-pyside6 kf6-kirigami kf6-qqc2-desktop-style qt6-qtwayland \
|
|
breeze-icon-theme plasma-breeze krdp freerdp tigervnc-x11-server xrandr \
|
|
&& dnf clean all
|
|
|
|
# uv, pinned. Python dependencies come from the committed uv.lock, not from
|
|
# whatever PyPI serves on build day.
|
|
RUN curl -fsSL https://github.com/astral-sh/uv/releases/download/0.12.23/uv-aarch64-unknown-linux-gnu.tar.gz \
|
|
| tar -xz --strip-components=1 -C /usr/local/bin
|
|
|
|
# OpenVR: the pinned public tag the Frame-side build scripts pin
|
|
# (screens/build.sh; the header SteamVR ships on the Frame predates the
|
|
# interface versions Frametop uses). The openvr repo carries the prebuilt
|
|
# linuxarm64 API library in its tree, so header and library come from the same
|
|
# commit; at runtime the library lives in /opt/frametop/lib, found through the
|
|
# binaries' rpath. (Valve no longer publishes release archives.)
|
|
RUN install -d /opt/frametop/include /opt/frametop/lib \
|
|
&& curl -fsSL https://github.com/ValveSoftware/openvr/raw/v2.15.6/headers/openvr.h -o /opt/frametop/include/openvr.h \
|
|
&& curl -fsSL https://github.com/ValveSoftware/openvr/raw/v2.15.6/headers/openvr_driver.h -o /opt/frametop/include/openvr_driver.h \
|
|
&& curl -fsSL https://github.com/ValveSoftware/openvr/raw/v2.15.6/bin/linuxarm64/libopenvr_api.so -o /opt/frametop/lib/libopenvr_api.so \
|
|
&& curl -fsSL https://raw.githubusercontent.com/nothings/stb/2c980bb59875b0d32144a71867fbdebb2f77cd20/stb_truetype.h \
|
|
-o /opt/frametop/include/stb_truetype.h
|
|
|
|
# Python environment from the lockfile (uv-managed CPython, not the system one:
|
|
# the venv must not depend on which Fedora is current). Rebuilt only when the
|
|
# lockfile changes, so source edits below reuse this layer. The environment
|
|
# variable comes first so the venv lands in /opt/frametop/venv.
|
|
ENV UV_PROJECT_ENVIRONMENT=/opt/frametop/venv
|
|
COPY pyproject.toml uv.lock .python-version /src/frametop/
|
|
RUN cd /src/frametop && uv sync --frozen --all-groups
|
|
|
|
# The sources, then the binaries (built as the Frame-side build scripts build
|
|
# them; outputs go to /opt/frametop/bin). Hand tracking is deferred exactly as
|
|
# in install.sh: it builds ncnn from source and isn't needed until
|
|
# hands/run.sh install runs.
|
|
COPY . /src/frametop
|
|
WORKDIR /src/frametop
|
|
RUN set -eux; mkdir -p /opt/frametop/bin
|
|
# ft-screens and ft-handtest (screens/build.sh, against /opt/frametop instead of /opt/steamvr)
|
|
RUN set -eux; cd screens; mkdir -p build; \
|
|
gcc -std=c11 -O2 -Wall -Wno-unused-parameter -c -o build/compositor.o compositor.c \
|
|
$(pkg-config --cflags wlroots-0.20 wayland-server xkbcommon libdrm pixman-1); \
|
|
cxx="g++ -std=c++17 -O2 -Wall -Wno-missing-field-initializers -I/opt/frametop/include $(pkg-config --cflags egl glesv2 gbm libdrm)"; \
|
|
$cxx -c -o build/vr.o vr.cpp; \
|
|
$cxx -c -o build/keyboard.o keyboard.cpp; \
|
|
$cxx -c -o build/handcut.o handcut.cpp; \
|
|
$cxx -c -o build/handtest.o handtest.cpp; \
|
|
vrlibs="$(pkg-config --libs egl glesv2 gbm) -L/opt/frametop/lib -lopenvr_api -Wl,-rpath,/opt/frametop/lib"; \
|
|
g++ -o /opt/frametop/bin/ft-screens build/compositor.o build/vr.o build/keyboard.o build/handcut.o \
|
|
$(pkg-config --libs wlroots-0.20 wayland-server xkbcommon pixman-1) $vrlibs; \
|
|
g++ -o /opt/frametop/bin/ft-handtest build/handtest.o build/handcut.o $vrlibs
|
|
# ft-pointer (pointer/helper/build.sh) and the ft_pointer driver (pointer/driver/build.sh;
|
|
# static C++ runtime, checked against the host's glibc 2.39)
|
|
RUN set -eux; cd pointer/helper; mkdir -p build; \
|
|
g++ -std=c++17 -O2 -Wall -Wno-unused-parameter -I/opt/frametop/include -I../common \
|
|
-o /opt/frametop/bin/ft-pointer ft-pointer.cpp \
|
|
-L/opt/frametop/lib -lopenvr_api -Wl,-rpath,/opt/frametop/lib -lpthread; \
|
|
cd ../driver; mkdir -p build; \
|
|
g++ -std=c++17 -O2 -fPIC -shared -fvisibility=hidden -fno-math-errno -Wall -Wno-unused-parameter \
|
|
-static-libstdc++ -static-libgcc -Wl,--exclude-libs,ALL \
|
|
-I/opt/frametop/include -o build/driver_ft_pointer.so driver_ft_pointer.cpp -lpthread; \
|
|
max=$(objdump -T build/driver_ft_pointer.so | grep -oE "GLIBC_[0-9.]+" | sort -uV | tail -1); \
|
|
[ "$(printf "%s\n" "$max" GLIBC_2.39 | sort -V | tail -1)" = GLIBC_2.39 ] \
|
|
|| { echo "driver needs newer glibc than the host has" >&2; exit 1; }; \
|
|
install -D build/driver_ft_pointer.so /opt/frametop/lib/driver_ft_pointer.so
|
|
# ft-gaze and ft-gazepanel (gaze/build.sh)
|
|
RUN set -eux; cd gaze; mkdir -p build; \
|
|
g++ -std=c++17 -O2 -Wall -Wno-unused-parameter -Wno-missing-field-initializers \
|
|
-I/opt/frametop/include -I../pointer/common \
|
|
-o /opt/frametop/bin/ft-gaze ft-gaze.cpp \
|
|
-L/opt/frametop/lib -lopenvr_api -Wl,-rpath,/opt/frametop/lib -lpthread; \
|
|
g++ -std=c++17 -O2 -Wall -Wno-unused-parameter -Wno-missing-field-initializers \
|
|
-I/opt/frametop/include $(pkg-config --cflags gbm libdrm) \
|
|
-o /opt/frametop/bin/ft-gazepanel panel/ft-gazepanel.cpp \
|
|
-L/opt/frametop/lib -lopenvr_api -Wl,-rpath,/opt/frametop/lib \
|
|
$(pkg-config --libs gbm libdrm) -lpthread
|
|
# ft-powerd (power/build.sh)
|
|
RUN set -eux; cd power; mkdir -p build; \
|
|
g++ -std=c++17 -O2 -Wall -Wno-unused-parameter -I/opt/frametop/include \
|
|
-o /opt/frametop/bin/ft-powerd ft-powerd.cpp \
|
|
-L/opt/frametop/lib -lopenvr_api -Wl,-rpath,/opt/frametop/lib
|
|
|
|
# The wrapper's default environment: Frametop's binaries and locked Python
|
|
# first, the system (dnf Qt stack) after. sleep infinity as the default command
|
|
# keeps the image usable with distrobox create, like the toolbox base.
|
|
ENV PATH=/opt/frametop/venv/bin:/opt/frametop/bin:/usr/local/bin:/usr/bin:/usr/sbin
|
|
CMD ["sleep", "infinity"]
|