mirror of
https://github.com/Toastconcern/FrameStudio.git
synced 2026-10-29 00:02:23 +01:00
Build Frame Home payload in CI Build the ARM64 headset payload against the glibc 2.39 baseline, validate its ABI, and pass the generated artifact to Studio packaging. Add provenance attestations and document CI and local build modes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
129 lines
6.8 KiB
Bash
Executable File
129 lines
6.8 KiB
Bash
Executable File
#!/bin/sh
|
|
# Builds Frame Studio for one or more computers and packages each into dist/, ready to hand out.
|
|
#
|
|
# scripts/build-studio.sh TARGET... [--build-dir DIR]
|
|
#
|
|
# Targets (each needs the matching compiler; GitHub Actions builds all of them: .github/workflows/build.yml):
|
|
# linux-x64 linux-x86 linux-arm64 on Linux: the native compiler (x86: gcc-multilib / g++-multilib); X11
|
|
# headers (libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev)
|
|
# windows-x64 windows-x86 windows-arm64 on Linux with llvm-mingw (cmake/llvm-mingw.cmake; $LLVM_MINGW)
|
|
# (on Windows itself: studio\build_windows.bat x64|x86|arm64)
|
|
# macos-arm64 macos-x64 on a Mac with Xcode's command line tools; MoltenVK is bundled into the
|
|
# app from $MOLTENVK (a libMoltenVK.dylib) or Homebrew's molten-vk
|
|
# all every target this computer can build
|
|
# Output: dist/FrameStudio-<target>.zip (.tar.gz on Linux).
|
|
set -eu
|
|
ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
|
DIST="$ROOT/dist"
|
|
BUILD="$ROOT/build"
|
|
FRAME_PAYLOAD_DIR=${FRAME_HOME_PAYLOAD_DIR:-"$ROOT/frame/payload"}
|
|
CMAKE=${CMAKE:-cmake}
|
|
TARGETS=""
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--build-dir) BUILD=$2; shift 2 ;;
|
|
-h|--help) sed -n '2,19p' "$0"; exit 0 ;;
|
|
*) TARGETS="$TARGETS $1"; shift ;;
|
|
esac
|
|
done
|
|
[ -n "$TARGETS" ] || { sed -n '2,19p' "$0"; exit 1; }
|
|
mkdir -p "$DIST" "$BUILD"
|
|
say() { echo "build-studio: $*"; }
|
|
|
|
if [ "$TARGETS" = " all" ]; then
|
|
case "$(uname -s)" in
|
|
Darwin) TARGETS="macos-arm64 macos-x64" ;;
|
|
*) case "$(uname -m)" in
|
|
aarch64|arm64) TARGETS="linux-arm64" ;;
|
|
*) TARGETS="linux-x64 linux-x86" ;;
|
|
esac
|
|
[ -x "${LLVM_MINGW:-$HOME/.local/opt/llvm-mingw}/bin/x86_64-w64-mingw32-clang" ] && TARGETS="$TARGETS windows-x64 windows-x86 windows-arm64" ;;
|
|
esac
|
|
fi
|
|
|
|
# configure + build one target; $1 target, then extra cmake arguments
|
|
build() {
|
|
target=$1; shift
|
|
dir="$BUILD/$target"
|
|
say "building $target"
|
|
"$CMAKE" -S "$ROOT/studio" -B "$dir" -DCMAKE_BUILD_TYPE=Release \
|
|
"-DFRAME_HOME_PAYLOAD_DIR=$FRAME_PAYLOAD_DIR" "$@" > "$dir.configure.log" 2>&1 || {
|
|
tail -20 "$dir.configure.log"; say "$target: configure failed (full log: $dir.configure.log)"; exit 1; }
|
|
"$CMAKE" --build "$dir" --target frame-studio --parallel
|
|
}
|
|
|
|
# Frame Home for SteamVR on the computer itself (Linux x64), built from the top-level project into
|
|
# $BUILD/<target>-home. $1 target, then extra cmake arguments.
|
|
build_pc_home() {
|
|
target=$1; shift
|
|
dir="$BUILD/$target-home"
|
|
say "building Frame Home for $target's SteamVR"
|
|
"$CMAKE" -S "$ROOT" -B "$dir" -DCMAKE_BUILD_TYPE=Release -DFRAME_HOME_PC=ON "$@" > "$dir.configure.log" 2>&1 || {
|
|
tail -20 "$dir.configure.log"; say "$target: Frame Home configure failed (full log: $dir.configure.log)"; exit 1; }
|
|
"$CMAKE" --build "$dir" --target frame-home frame-switcher --parallel
|
|
}
|
|
|
|
# pc/ beside Studio: Frame Home for this computer's SteamVR and its installer (Studio's Headset tab runs it), the Steam
|
|
# Frame's way — the Vulkan compositor layer draws the home in Aurora's place, installed with the headset's own
|
|
# install.sh (Linux only).
|
|
stage_pc() {
|
|
target=$1 stage=$2 home="$BUILD/$1-home"
|
|
case "$target" in
|
|
linux-x64) mkdir -p "$stage/pc/bin" "$stage/pc/layer"
|
|
cp "$home/frame-home" "$home/frame-switcher" "$stage/pc/bin/"
|
|
${CXX:-g++} -O2 -shared -fPIC -std=c++17 -fvisibility=hidden -I"$ROOT/third_party/vulkan-headers/include" -I"$ROOT/src" \
|
|
"$ROOT/layer/frame_home_layer.cpp" -o "$stage/pc/layer/libframe_home_layer.so" -lpthread
|
|
cp "$FRAME_PAYLOAD_DIR/layer/env_ps.spv" "$stage/pc/layer/"
|
|
cp "$FRAME_PAYLOAD_DIR/install.sh" "$stage/pc/" && chmod +x "$stage/pc/install.sh" "$stage"/pc/bin/* ;;
|
|
esac
|
|
}
|
|
|
|
# dist/FrameStudio-<target>: the program and, beside it, frame/ (the headset side Studio installs) and pc/ (Frame Home
|
|
# for this computer's SteamVR, where there is one)
|
|
package() {
|
|
target=$1 dir="$BUILD/$1" name="FrameStudio-$1"
|
|
stage="$BUILD/stage/$name"
|
|
rm -rf "$stage" && mkdir -p "$stage"
|
|
cp "$ROOT/LICENSE" "$stage/LICENSE.txt"
|
|
case "$target" in
|
|
windows-*) cp "$dir/Frame Studio.exe" "$stage/" && cp -R "$dir/frame" "$stage/frame"
|
|
stage_pc "$target" "$stage"
|
|
(cd "$BUILD/stage" && rm -f "$DIST/$name.zip" && zip -qr "$DIST/$name.zip" "$name") ;;
|
|
linux-*) cp "$dir/Frame Studio" "$stage/" && cp -R "$dir/frame" "$stage/frame"
|
|
stage_pc "$target" "$stage"
|
|
tar -czf "$DIST/$name.tar.gz" -C "$BUILD/stage" "$name" ;;
|
|
macos-*) cp -R "$dir/Frame Studio.app" "$stage/"
|
|
bundle_moltenvk "$stage/Frame Studio.app"
|
|
(cd "$BUILD/stage" && rm -f "$DIST/$name.zip" && ditto -c -k --keepParent "$name" "$DIST/$name.zip") ;;
|
|
esac
|
|
say "$target -> dist/$(ls "$DIST" | grep "^$name\." | head -1)"
|
|
}
|
|
|
|
# MoltenVK (Vulkan on Metal) inside the app: Contents/Frameworks/libMoltenVK.dylib, which Studio loads itself when
|
|
# the Mac has no Vulkan loader installed.
|
|
bundle_moltenvk() {
|
|
app=$1
|
|
lib=${MOLTENVK:-}
|
|
[ -n "$lib" ] || { command -v brew > /dev/null && lib="$(brew --prefix molten-vk 2>/dev/null)/lib/libMoltenVK.dylib"; } || true
|
|
if [ -n "$lib" ] && [ -f "$lib" ]; then
|
|
mkdir -p "$app/Contents/Frameworks" && cp "$lib" "$app/Contents/Frameworks/"
|
|
else
|
|
say "warning: no MoltenVK found (set MOLTENVK or: brew install molten-vk): the app needs the Vulkan SDK installed to run"
|
|
fi
|
|
}
|
|
|
|
for t in $TARGETS; do
|
|
case "$t" in
|
|
linux-x64) build "$t" -G Ninja && build_pc_home "$t" -G Ninja && package "$t" ;;
|
|
linux-arm64) build "$t" -G Ninja && package "$t" ;;
|
|
linux-x86) build "$t" -G Ninja -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 -DCMAKE_SYSTEM_PROCESSOR=i686 \
|
|
-DCMAKE_LIBRARY_ARCHITECTURE=i386-linux-gnu && package "$t" ;;
|
|
windows-x64) build "$t" -G Ninja -DCMAKE_TOOLCHAIN_FILE="$ROOT/cmake/llvm-mingw.cmake" -DWINDOWS_ARCH=x86_64 && package "$t" ;;
|
|
windows-x86) build "$t" -G Ninja -DCMAKE_TOOLCHAIN_FILE="$ROOT/cmake/llvm-mingw.cmake" -DWINDOWS_ARCH=i686 && package "$t" ;;
|
|
windows-arm64) build "$t" -G Ninja -DCMAKE_TOOLCHAIN_FILE="$ROOT/cmake/llvm-mingw.cmake" -DWINDOWS_ARCH=aarch64 && package "$t" ;;
|
|
macos-arm64) build "$t" -G Ninja -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 && package "$t" ;;
|
|
macos-x64) build "$t" -G Ninja -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 && package "$t" ;;
|
|
*) say "unknown target: $t (see --help)"; exit 1 ;;
|
|
esac
|
|
done
|