Skip to content

Instantly share code, notes, and snippets.

@martpie
Last active September 23, 2026 20:31
Show Gist options
  • Select an option

  • Save martpie/2b5e108f0d173c85bcbb84843d93c839 to your computer and use it in GitHub Desktop.

Select an option

Save martpie/2b5e108f0d173c85bcbb84843d93c839 to your computer and use it in GitHub Desktop.
Build gamescope from source for Pop!_OS 24.04 (COSMIC)
#!/usr/bin/env bash
# Build gamescope on Pop!_OS / Ubuntu 24.04.
# 24.04's libdrm, libxkbcommon and pixman are too old for gamescope's
# bundled wlroots, so we build newer copies into a private prefix
# (/opt/gamescope) without touching the system libraries.
set -euo pipefail
# To update: bump GAMESCOPE_TAG (or any dep tag below) and re-run the script.
# Existing checkouts are moved to the new tag, submodules included.
GAMESCOPE_TAG=3.16.29
LIBDRM_TAG=libdrm-2.4.129 # wlroots 0.20 needs >= 2.4.129 (24.04 has 2.4.125)
LIBXKBCOMMON_TAG=xkbcommon-1.12.3 # 24.04 has 1.6; 1.13+ needs a newer meson than 24.04's
PIXMAN_TAG=pixman-0.46.4 # wlroots needs >= 0.43 (24.04 has 0.42)
# libwayland and wayland-protocols always use their latest release (see below).
PREFIX=/opt/gamescope
SRC="$PWD" # everything is cloned/built in the folder you run the script from
LIBDIR="$PREFIX/lib/x86_64-linux-gnu"
# 1. Build tools + system deps that are new enough on 24.04
sudo apt install -y build-essential git meson ninja-build cmake pkg-config glslang-tools \
libxml2-dev libexpat1-dev libffi-dev \
libx11-dev libxdamage-dev libxcomposite-dev libxcursor-dev libxxf86vm-dev libxtst-dev \
libxres-dev libxmu-dev libxkbcommon-dev libvulkan-dev libsdl2-dev libdecor-0-dev \
libpipewire-0.3-dev libcap-dev libseat-dev libinput-dev libudev-dev libdisplay-info-dev \
libluajit-5.1-dev libavif-dev libbenchmark-dev libgbm-dev libegl-dev \
libxcb-composite0-dev libxcb-icccm4-dev libxcb-res0-dev libxcb-ewmh-dev wayland-protocols \
libxfixes-dev libxext-dev libxi-dev libxrender-dev libxrandr-dev libeis-dev \
xwayland hwdata libpciaccess-dev bison libxcb-xkb-dev patchelf file libx11-xcb-dev liblcms2-dev
sudo mkdir -p "$PREFIX" && sudo chown "$USER" "$PREFIX"
mkdir -p "$SRC" && cd "$SRC"
export PKG_CONFIG_PATH="$LIBDIR/pkgconfig:$PREFIX/share/pkgconfig"
export PATH="$PREFIX/bin:$PATH"
export LDFLAGS="-Wl,-rpath,$LIBDIR" # binaries find our libs (see step 4 for Steam)
# Clone repo, or move an existing checkout to the requested tag.
sync_repo() { # dir git-url tag
local dir=$1 url=$2 tag=$3
if [ ! -d "$dir/.git" ]; then
git clone --recursive -b "$tag" "$url" "$dir"
else
git -C "$dir" fetch --tags --force origin
git -C "$dir" checkout --force "refs/tags/$tag"
git -C "$dir" submodule sync --recursive
git -C "$dir" submodule update --init --recursive --force
fi
}
build_dep() { # name git-url tag [meson options...]
local name=$1 url=$2 tag=$3; shift 3
sync_repo "$name" "$url" "$tag"
meson setup "$name/build" "$name" --prefix="$PREFIX" --libdir=lib/x86_64-linux-gnu \
--buildtype=release --wipe "$@" 2>/dev/null || \
meson setup "$name/build" "$name" --prefix="$PREFIX" --libdir=lib/x86_64-linux-gnu \
--buildtype=release "$@"
ninja -C "$name/build"
meson install -C "$name/build"
}
# 2. Newer libwayland, wayland-protocols, libdrm, libxkbcommon and pixman into /opt/gamescope
# libwayland: latest release. Its wayland-scanner is needed to build the latest
# wayland-protocols (older scanners reject the new "frozen" attribute).
latest_tag() { git ls-remote --tags --refs "$1" | grep -oE "$2" | grep -vE "\.9[0-9]$" | sort -V | tail -1; } # skip x.y.9x pre-releases
WL_URL=https://gitlab.freedesktop.org/wayland/wayland.git
build_dep wayland "$WL_URL" "$(latest_tag "$WL_URL" '[0-9]+\.[0-9]+\.[0-9]+$')" \
-Ddocumentation=false -Dtests=false
# wlroots 0.20 needs a newer wayland-protocols than 24.04's 1.45: use the latest release tag
WLP_URL=https://gitlab.freedesktop.org/wayland/wayland-protocols.git
build_dep wayland-protocols "$WLP_URL" "$(latest_tag "$WLP_URL" '[0-9]+\.[0-9]+$')" -Dtests=false
build_dep libdrm https://gitlab.freedesktop.org/mesa/drm.git "$LIBDRM_TAG" \
-Dtests=false -Dman-pages=disabled -Dvalgrind=disabled -Dcairo-tests=disabled
build_dep libxkbcommon https://github.com/xkbcommon/libxkbcommon.git "$LIBXKBCOMMON_TAG" \
-Denable-docs=false -Denable-wayland=false -Denable-tools=false -Denable-bash-completion=false \
-Dxkb-config-root=/usr/share/X11/xkb -Dx-locale-root=/usr/share/X11/locale
build_dep pixman https://gitlab.freedesktop.org/pixman/pixman.git "$PIXMAN_TAG" \
-Dtests=disabled -Ddemos=disabled -Dgtk=disabled
# 3. gamescope itself (wlroots, libliftoff, vkroots... come as bundled subprojects)
sync_repo gamescope https://github.com/ValveSoftware/gamescope.git "$GAMESCOPE_TAG"
cd gamescope
meson setup build --prefix="$PREFIX" --buildtype=release -Denable_tests=false --wipe 2>/dev/null || \
meson setup build --prefix="$PREFIX" --buildtype=release -Denable_tests=false
ninja -C build
meson install -C build --skip-subprojects
# 4. Force a DT_RPATH on gamescope's binaries. Unlike RUNPATH, RPATH wins over
# LD_LIBRARY_PATH, so Steam's library path can't make gamescope load 24.04's
# old libwayland (-> "undefined symbol: wl_resource_post_error_vargs").
for bin in "$PREFIX"/bin/gamescope*; do
if file -b "$bin" | grep -q ELF; then
patchelf --force-rpath --set-rpath "$LIBDIR" "$bin"
fi
done
readelf -d "$PREFIX/bin/gamescope" | grep -E 'RPATH|RUNPATH'
# 5. Put gamescope's binaries on PATH (gamescope launches helpers like
# gamescopereaper by name, so they all need to be on PATH, not just gamescope).
# Only gamescope* is linked; our private wayland-scanner etc. stay in /opt.
for bin in "$PREFIX"/bin/gamescope*; do
sudo ln -sf "$bin" "/usr/local/bin/$(basename "$bin")"
done
gamescope --version
echo "Done. Uninstall with: bash uninstall-gamescope.sh"
sudo apt install vulkan-tools
gamescope -W 2560 -H 1440 -r 120 -- vkcube
#!/usr/bin/env bash
# Uninstall gamescope built with build-gamescope.sh (Pop!_OS 24.04, COSMIC).
# Everything was installed into /opt/gamescope + /usr/local/bin/gamescope* symlinks, so nothing
# else on the system is touched.
#
# Usage:
# bash uninstall-gamescope.sh # remove the installed gamescope
# bash uninstall-gamescope.sh --sources # also delete the cloned sources in the current folder
set -euo pipefail
PREFIX=/opt/gamescope
# Remove /usr/local/bin/gamescope* links, only if they point into our prefix
for link in /usr/local/bin/gamescope*; do
if [ -L "$link" ] && [[ "$(readlink "$link")" == "$PREFIX"/* ]]; then
sudo rm -f "$link"
echo "Removed $link"
fi
done
if [ -d "$PREFIX" ]; then
sudo rm -rf "$PREFIX"
echo "Removed $PREFIX"
fi
if [ "${1:-}" = "--sources" ]; then
for d in gamescope wayland wayland-protocols libdrm libxkbcommon pixman; do
[ -d "$d" ] && rm -rf "$d" && echo "Removed ./$d"
done
fi
hash -r
if command -v gamescope >/dev/null; then
echo "Note: another gamescope is still on PATH: $(command -v gamescope)"
else
echo "gamescope uninstalled."
fi
# The apt build dependencies are left installed (other software may use them).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment