mirror of
https://github.com/nestriness/nestri.git
synced 2026-09-27 04:52:25 +03:00
feat: media bitrate control, HDR (#346)
Fixes: #335 Still a work-in-progress. --------- Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Wanjohi <elviswanjohi47@gmail.com>
This commit is contained in:
co-authored by
DatCaptainHorse
Claude Opus 5
Wanjohi
parent
1c721962f4
commit
0811f57f1a
+137
-83
@@ -1,96 +1,150 @@
|
||||
#!/usr/bin/env bash
|
||||
# Builds proton-cachyos from the tree proton-fetch.sh laid down. Container-only.
|
||||
# Builds proton-ge wow64-only and leaves the finished tree in "${PROTON_WORK}/obj/dist".
|
||||
# Runs on the host, not in a container.
|
||||
#
|
||||
# The one thing that matters here is --enable-wow64: it builds wine so that
|
||||
# 32-bit Windows code runs inside a 64-bit unix process, thunking down to the
|
||||
# 64-bit host libraries. Without it, Proton needs a complete 32-bit host stack —
|
||||
# lib32 glibc, a second Mesa built for i686, and a second nescapture layer,
|
||||
# because a 32-bit game would load the 32-bit Vulkan loader and our 64-bit
|
||||
# capture layer would be invisible to it. With it, none of that exists.
|
||||
# It has to run on the host because proton-ge's build is itself container-driven:
|
||||
# `make` runs outside, and every step runs in the Steam Runtime SDK image, where
|
||||
# the toolchains live, through the engine it is configured with. There is no
|
||||
# mode without a container, and a container engine inside `podman build` is
|
||||
# nested containers, which is a lot of fragile setup for no gain. So the only
|
||||
# thing this script needs from the host is git, make and the engine. The
|
||||
# Makefile packages the result afterwards.
|
||||
#
|
||||
# The cost is that the distro package cannot be used: proton-cachyos-native is
|
||||
# packaged without the flag, which is exactly why it depends on lib32-*.
|
||||
# The one thing we change is the arch list: it becomes wow64-only, and that
|
||||
# change is the reason this is our own build and not a download. wow64 runs
|
||||
# 32-bit Windows code inside a 64-bit unix process. Without it Proton needs a
|
||||
# complete 32-bit host stack: lib32 glibc, a second Mesa built for i686, and a
|
||||
# second nescapture layer, because a 32-bit game would load the 32-bit Vulkan
|
||||
# loader and our 64-bit capture layer would be invisible to it. The released
|
||||
# builds carry an i386 unix side, which is exactly why they need lib32-*.
|
||||
#
|
||||
# Everything else is proton-ge's own recipe: the same SDK image, the same flags
|
||||
# and the same patch set. The one addition is patches/proton-ge/: fixes for the
|
||||
# places its makefile assumes a 32-bit unix side that wow64 does not have, and
|
||||
# for things a tag pinned that have since moved out from under it.
|
||||
set -euo pipefail
|
||||
|
||||
: "${GECKO_VER:?}"
|
||||
: "${MONO_VER:?}"
|
||||
: "${PROTON_GIT:?}"
|
||||
: "${PROTON_TAG:?}"
|
||||
: "${PROTON_WORK:?}"
|
||||
: "${BUILD_NAME:?}"
|
||||
|
||||
ENGINE="${CONTAINER_ENGINE:-podman}"
|
||||
JOBS="${JOBS:-$(nproc)}"
|
||||
BUILD_NAME="proton-cachyos"
|
||||
SRC_DIR="/build/proton-cachyos"
|
||||
BUILD_DIR="/build/build"
|
||||
OUT_DIR="/artifacts/proton/usr/share/steam/compatibilitytools.d/${BUILD_NAME}"
|
||||
|
||||
[[ -d "${SRC_DIR}" ]] || { echo "no source tree — proton-fetch.sh did not run"; exit 1; }
|
||||
mkdir -p "${PROTON_WORK}"
|
||||
PROTON_WORK="$(cd "${PROTON_WORK}" && pwd)"
|
||||
SRC="${PROTON_WORK}/src"
|
||||
OBJ="${PROTON_WORK}/obj"
|
||||
STAMP_TAG="${PROTON_WORK}/.tag"
|
||||
STAMP_PATCHED="${PROTON_WORK}/.patched"
|
||||
PATCH_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../patches/proton-ge" && pwd)"
|
||||
|
||||
# ── Toolchain wrappers ──────────────────────────────────
|
||||
# Proton's build calls the compiler by GNU triplet. Arch's gcc does not install
|
||||
# under those names, so stand in for them. The i686 set is generated too: with
|
||||
# wow64 nothing should reach for it, and if something does, failing on a missing
|
||||
# 32-bit header beats silently building a 32-bit unix library we then have to
|
||||
# ship libraries for.
|
||||
WRAP=/build/wrappers
|
||||
rm -rf "$WRAP" && mkdir -p "$WRAP"
|
||||
_wrappers() {
|
||||
local arch="$1" gccflag="$2" ldflag="$3" asflag="$4" stripfmt="$5"
|
||||
local l t
|
||||
for l in ar ranlib nm; do
|
||||
ln -sf "/usr/bin/gcc-${l}" "${WRAP}/${arch}-pc-linux-gnu-${l}"
|
||||
# Two builds in one tree do not fail cleanly. They race on the same objects and
|
||||
# leave half-written files that a later build trusts. A failed make also keeps
|
||||
# running its in-flight jobs for a while after it reports the error, so the
|
||||
# first build is often still running when the second one starts.
|
||||
exec 9>"${PROTON_WORK}/.lock"
|
||||
flock -n 9 || { echo "proton: another build is using ${PROTON_WORK}" >&2; exit 1; }
|
||||
|
||||
# ccache and cargo's downloads are kept outside src/ and obj/, so a new tag or
|
||||
# FORCE_REBUILD throws away the build and keeps the parts that are correct to
|
||||
# reuse. proton-ge's makefile mounts both into the container from these
|
||||
# variables.
|
||||
export CCACHE_DIR="${PROTON_WORK}/ccache"
|
||||
export CARGO_HOME="${PROTON_WORK}/cargo"
|
||||
mkdir -p "${CCACHE_DIR}" "${CARGO_HOME}"
|
||||
|
||||
if [[ -n "${FORCE_REBUILD:-}" || "$(cat "${STAMP_TAG}" 2>/dev/null)" != "${PROTON_TAG}" ]]; then
|
||||
echo "proton: fresh tree for ${PROTON_TAG}"
|
||||
rm -rf "${SRC}" "${OBJ}" "${STAMP_TAG}" "${STAMP_PATCHED}"
|
||||
fi
|
||||
|
||||
# ── Fetch ───────────────────────────────────────────────
|
||||
if [[ ! -e "${STAMP_TAG}" ]]; then
|
||||
rm -rf "${SRC}"
|
||||
git clone --branch "${PROTON_TAG}" --depth=1 "${PROTON_GIT}" "${SRC}"
|
||||
# No --depth here: submodules are pinned to commits that are often not a
|
||||
# branch tip. --filter=tree:0 keeps the download down instead.
|
||||
git -C "${SRC}" submodule update --init --filter=tree:0 --recursive
|
||||
echo "${PROTON_TAG}" > "${STAMP_TAG}"
|
||||
fi
|
||||
|
||||
# The SDK image is pinned by proton-ge's own makefile, per tag. Asking it keeps
|
||||
# the patch step below and the build on the same image.
|
||||
SDK_IMAGE="$(make --silent --no-print-directory -f "${SRC}/Makefile.in" \
|
||||
SRCDIR="${SRC}" get-steamrt-image)"
|
||||
|
||||
# ── Patch ───────────────────────────────────────────────
|
||||
# The patch script edits the tree in place and is not idempotent: it resets
|
||||
# some submodules first and not others. So a tree is patched once, and one that
|
||||
# was interrupted halfway is reset to the commits the tag pins before trying
|
||||
# again.
|
||||
#
|
||||
# It is run in the SDK image rather than on the host, so it does not depend on
|
||||
# the host's python, patch or wget.
|
||||
#
|
||||
# The script carries on past a patch that does not apply and exits 0 anyway.
|
||||
# The upstream instructions are to grep its output for failures, so that is
|
||||
# what happens here. The alternative is an image that looks fine and is missing
|
||||
# a fix.
|
||||
#
|
||||
# A build tree does not survive its source being re-patched. Changing
|
||||
# Makefile.in re-syncs every component's source copy, but a component's
|
||||
# configure step depends on that sync order-only, so it does not rerun, and its
|
||||
# old build directory is left pointing at generated autotools files the sync
|
||||
# just removed. So patching starts obj/ over too. ccache keeps that cheap.
|
||||
if [[ ! -e "${STAMP_PATCHED}" ]]; then
|
||||
rm -rf "${OBJ}"
|
||||
git -C "${SRC}" reset -q --hard
|
||||
git -C "${SRC}" submodule foreach -q --recursive 'git reset -q --hard && git clean -qfdx'
|
||||
"${ENGINE}" run --rm -v "${SRC}:${SRC}" -w "${SRC}" "${SDK_IMAGE}" \
|
||||
./patches/protonprep-valve-staging.sh 2>&1 | tee "${PROTON_WORK}/patch.log"
|
||||
if grep -Ei 'hunk .* failed|saving rejects|can.t find file|malformed patch|skipping patch|^error' \
|
||||
"${PROTON_WORK}/patch.log"; then
|
||||
echo "proton: patches did not apply cleanly, see ${PROTON_WORK}/patch.log" >&2
|
||||
exit 1
|
||||
fi
|
||||
# Ours go on top. They are paths from the root of the tree, submodules
|
||||
# included. `git apply` fails outright on a patch that no longer applies,
|
||||
# which is what a tag bump should do: each one says why it exists, so the
|
||||
# question is only whether upstream fixed it.
|
||||
for p in "${PATCH_DIR}"/*.patch; do
|
||||
[[ -e "$p" ]] || continue
|
||||
echo "proton: applying $(basename "$p")"
|
||||
git -C "${SRC}" apply "$p"
|
||||
done
|
||||
for t in gcc g++; do
|
||||
printf '#!/usr/bin/bash\n/usr/bin/%s %s "$@"\n' "$t" "$gccflag" \
|
||||
> "${WRAP}/${arch}-pc-linux-gnu-${t}"
|
||||
chmod 755 "${WRAP}/${arch}-pc-linux-gnu-${t}"
|
||||
done
|
||||
printf '#!/usr/bin/bash\n/usr/bin/ld %s "$@"\n' "$ldflag" > "${WRAP}/${arch}-pc-linux-gnu-ld"
|
||||
printf '#!/usr/bin/bash\n/usr/bin/as %s "$@"\n' "$asflag" > "${WRAP}/${arch}-pc-linux-gnu-as"
|
||||
printf '#!/usr/bin/bash\n/usr/bin/strip -F %s "$@"\n' "$stripfmt" > "${WRAP}/${arch}-pc-linux-gnu-strip"
|
||||
chmod 755 "${WRAP}/${arch}-pc-linux-gnu-"{ld,as,strip}
|
||||
}
|
||||
_wrappers x86_64 "-m64" "-melf_x86_64" "--64" "elf64-x86-64"
|
||||
_wrappers i686 "-m32" "-melf_i386" "--32" "elf32-i386"
|
||||
export PATH="${WRAP}:${PATH}"
|
||||
touch "${STAMP_PATCHED}"
|
||||
fi
|
||||
|
||||
# ── Configure ───────────────────────────────────────────
|
||||
# configure.sh refuses an in-tree build, and it test-runs the SDK image to work
|
||||
# out how the engine maps file ownership, so it is also where a broken engine
|
||||
# setup shows up first.
|
||||
mkdir -p "${OBJ}"
|
||||
if [[ ! -e "${OBJ}/Makefile" ]]; then
|
||||
(cd "${OBJ}" && "${SRC}/configure.sh" \
|
||||
--build-name="${BUILD_NAME}" \
|
||||
--container-engine="${ENGINE}")
|
||||
fi
|
||||
|
||||
# ── Build ───────────────────────────────────────────────
|
||||
# -march=nocona matches the distro packaging: Proton has to run on whatever CPU
|
||||
# the guest is given, and the VMM does not promise a feature level.
|
||||
export CFLAGS="-O3 -march=nocona -mtune=core-avx2"
|
||||
export CXXFLAGS="${CFLAGS}"
|
||||
export RUSTFLAGS="-C opt-level=3 -C target-cpu=nocona"
|
||||
export LDFLAGS="-Wl,-O1,--sort-common,--as-needed"
|
||||
export RUSTUP_TOOLCHAIN=stable
|
||||
# ARCHS drops i386-unix, which leaves wine configured for x86_64 unix with an
|
||||
# i386 PE side. That is wow64. Every component rule is gated on ARCHS, so the
|
||||
# 32-bit unix builds of everything else go with it. ENABLE_WOW64 makes the
|
||||
# proton script ask wine for a wow64 prefix. proton-ge ships it as a switch
|
||||
# but never turns it on.
|
||||
#
|
||||
# A command-line variable reaches the container build too: the outer make
|
||||
# hands its overrides to the inner one.
|
||||
#
|
||||
# SOURCE_DATE_EPOCH is the tag's commit time rather than now, so two builds of
|
||||
# one tag stamp the same dates into their output.
|
||||
make -C "${OBJ}" \
|
||||
J="${JOBS}" \
|
||||
ARCHS="i386-windows x86_64-windows x86_64-unix" \
|
||||
ENABLE_WOW64=1 \
|
||||
SOURCE_DATE_EPOCH="$(git -C "${SRC}" log -1 --format=%ct)" \
|
||||
dist
|
||||
|
||||
mkdir -p "${BUILD_DIR}"
|
||||
cd "${BUILD_DIR}"
|
||||
|
||||
ROOTLESS_CONTAINER="" \
|
||||
"${SRC_DIR}/configure.sh" \
|
||||
--container-engine="none" \
|
||||
--proton-sdk-image="" \
|
||||
--build-name="${BUILD_NAME}" \
|
||||
--without-extras=all \
|
||||
--without-vklayers=all \
|
||||
--without-steamrt-depends \
|
||||
--without-tts \
|
||||
--without-nvidia-libs \
|
||||
--enable-wow64
|
||||
|
||||
# The top-level make is serial by design; SUBJOBS is what it hands to each
|
||||
# component's build.
|
||||
SUBJOBS="${JOBS}" make -j1 dist
|
||||
|
||||
# ── Install ─────────────────────────────────────────────
|
||||
mkdir -p "${OUT_DIR}"
|
||||
cp -a "${BUILD_DIR}/dist/." "${OUT_DIR}/"
|
||||
|
||||
# Debug symbols in the bundled PE runtimes are dead weight in a guest image.
|
||||
cd "${OUT_DIR}/files"
|
||||
find "share/wine/gecko/wine-gecko-${GECKO_VER}-x86" -name '*.dll' -o -name '*.exe' 2>/dev/null \
|
||||
| xargs -r i686-w64-mingw32-strip --strip-debug 2>/dev/null || true
|
||||
find "share/wine/gecko/wine-gecko-${GECKO_VER}-x86_64" -name '*.dll' -o -name '*.exe' 2>/dev/null \
|
||||
| xargs -r x86_64-w64-mingw32-strip --strip-debug 2>/dev/null || true
|
||||
find "share/wine/mono/wine-mono-${MONO_VER}" -name '*.dll' -o -name '*.exe' 2>/dev/null \
|
||||
| xargs -r i686-w64-mingw32-strip --strip-debug 2>/dev/null || true
|
||||
|
||||
rm -rf "${BUILD_DIR}"
|
||||
echo "proton: installed to ${OUT_DIR}"
|
||||
echo "proton: built ${OBJ}/dist"
|
||||
|
||||
Reference in New Issue
Block a user