Commit a3ccb7f5 authored by K900's avatar K900
Browse files

steam: decimate

parent 70cb669a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ in {
      default = pkgs.steam;
      defaultText = lib.literalExpression "pkgs.steam";
      example = lib.literalExpression ''
        pkgs.steam-small.override {
        pkgs.steam.override {
          extraEnv = {
            MANGOHUD = true;
            OBS_VKCAPTURE = true;
+3 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
, targetPkgs ? pkgs: []
, multiPkgs ? pkgs: []
, multiArch ? false # Whether to include 32bit packages
, includeClosures ? false # Whether to include closures of all packages
, nativeBuildInputs ? []
, extraBuildCommands ? ""
, extraBuildCommandsMulti ? ""
@@ -171,6 +172,7 @@ let
          ${pkgs.glib.dev}/bin/glib-compile-schemas $out/share/glib-2.0/schemas
      fi
    '';
    inherit includeClosures;
  };

  staticUsrProfileMulti = buildEnv {
@@ -178,6 +180,7 @@ let
    paths = baseMultiPaths ++ multiPaths;
    extraOutputsToInstall = [ "out" "lib" ] ++ extraOutputsToInstall;
    ignoreCollisions = true;
    inherit includeClosures;
  };

  # setup library paths only for the targeted architecture
+2 −15
Original line number Diff line number Diff line
{ makeScopeWithSplicing', generateSplicesForMkScope
, stdenv, buildFHSEnv, pkgsi686Linux, mesa-demos
, stdenv
}:

let
@@ -10,21 +10,8 @@ let
                else if stdenv.hostPlatform.system == "i686-linux" then "i386"
                else throw "Unsupported platform: ${stdenv.hostPlatform.system}";

    steam-runtime = callPackage ./runtime.nix { };
    steam-runtime-wrapped = callPackage ./runtime-wrapped.nix { };
    steam = callPackage ./steam.nix { };
    steam-fhsenv = callPackage ./fhsenv.nix {
      mesa-demos-i686 =
        if self.steamArch == "amd64"
        then pkgsi686Linux.mesa-demos
        else mesa-demos;
      steam-runtime-wrapped-i686 =
        if self.steamArch == "amd64"
        then pkgsi686Linux.steamPackages.steam-runtime-wrapped
        else null;
      inherit buildFHSEnv;
    };
    steam-fhsenv-small = steam-fhsenv.override { withGameSpecificLibraries = false; };
    steam-fhsenv = callPackage ./fhsenv.nix {};

    # This has to exist so Hydra tries to build all of Steam's dependencies.
    # FIXME: Maybe we should expose it as something more generic?
+111 −320
Original line number Diff line number Diff line
{ lib, stdenv, writeShellScript, buildFHSEnv, steam, mesa-demos-i686
, steam-runtime-wrapped, steam-runtime-wrapped-i686 ? null
, extraPkgs ? pkgs: [ ] # extra packages to add to targetPkgs
, extraLibraries ? pkgs: [ ] # extra packages to add to multiPkgs
, extraProfile ? "" # string to append to profile
, extraPreBwrapCmds ? "" # extra commands to run before calling bubblewrap (real default is at usage site)
, extraBwrapArgs ? [ ] # extra arguments to pass to bubblewrap (real default is at usage site)
, extraArgs ? "" # arguments to always pass to steam
, extraEnv ? { } # Environment variables to pass to Steam

# steamwebhelper deletes unrelated electron programs' singleton cookies from /tmp on startup:
# https://github.com/ValveSoftware/steam-for-linux/issues/9121
, privateTmp ? true # Whether to separate steam's /tmp from the host system

, withGameSpecificLibraries ? true # include game specific libraries
}@args:

{
  lib,
  steam,
  buildFHSEnv,
  writeShellScript,
  extraPkgs ? pkgs: [ ], # extra packages to add to targetPkgs
  extraLibraries ? pkgs: [ ], # extra packages to add to multiPkgs
  extraProfile ? "", # string to append to profile
  extraPreBwrapCmds ? "", # extra commands to run before calling bubblewrap
  extraBwrapArgs ? [ ], # extra arguments to pass to bubblewrap (real default is at usage site)
  extraArgs ? "", # arguments to always pass to steam
  extraEnv ? { }, # Environment variables to pass to Steam
}:
let
  commonTargetPkgs = pkgs: with pkgs; [
    # Needed for operating system detection until
    # https://github.com/ValveSoftware/steam-for-linux/issues/5909 is resolved
    lsb-release
    # Errors in output without those
    pciutils
    # run.sh wants ldconfig
    glibc_multi.bin
    # Games' dependencies
    xorg.xrandr
    which
    # Needed by gdialog, including in the steam-runtime
    perl
    # Open URLs
    xdg-utils
    iana-etc
    # Steam Play / Proton
    python3
    # Steam VR
    procps
    usbutils

    # It tries to execute xdg-user-dir and spams the log with command not founds
    xdg-user-dirs

    # electron based launchers need newer versions of these libraries than what runtime provides
    mesa
    sqlite
  ] ++ extraPkgs pkgs;

  ldPath = lib.optionals stdenv.hostPlatform.is64bit [ "/lib64" ]
  ++ [ "/lib32" ]
  ++ map (x: "/steamrt/${steam-runtime-wrapped.arch}/" + x) steam-runtime-wrapped.libs
  ++ lib.optionals (steam-runtime-wrapped-i686 != null) (map (x: "/steamrt/${steam-runtime-wrapped-i686.arch}/" + x) steam-runtime-wrapped-i686.libs);

  # Zachtronics and a few other studios expect STEAM_LD_LIBRARY_PATH to be present
  exportLDPath = ''
    export LD_LIBRARY_PATH=${lib.concatStringsSep ":" ldPath}''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH
    export STEAM_LD_LIBRARY_PATH="$STEAM_LD_LIBRARY_PATH''${STEAM_LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH"
  '';

  # bootstrap.tar.xz has 444 permissions, which means that simple deletes fail
  # and steam will not be able to start
  fixBootstrap = ''
    if [ -r $HOME/.steam/steam/bootstrap.tar.xz ]; then
      chmod +w $HOME/.steam/steam/bootstrap.tar.xz
    fi
  '';

  envScript = ''
    # prevents various error messages
    unset GIO_EXTRA_MODULES
  steamEnv = { name, runScript, passthru ? {}, meta ? {} }:
  buildFHSEnv {
    inherit name runScript passthru meta;

    # This is needed for IME (e.g. iBus, fcitx5) to function correctly on non-CJK locales
    # https://github.com/ValveSoftware/steam-for-linux/issues/781#issuecomment-2004757379
    GTK_IM_MODULE='xim'
  '' + lib.toShellVars extraEnv;

in buildFHSEnv rec {
  name = "steam";

  # Steam still needs 32bit and various native games do too
    multiArch = true;
    includeClosures = true;

    # https://gitlab.steamos.cloud/steamrt/steam-runtime-tools/-/blob/main/docs/distro-assumptions.md#command-line-tools
    targetPkgs = pkgs: with pkgs; [
      steam
    # License agreement

      bash
      coreutils
      file
      lsb-release  # not documented, called from Big Picture
      pciutils  # not documented, complains about lspci on startup
      glibc_multi.bin
      xz
      zenity
  ] ++ commonTargetPkgs pkgs;

      # Steam expects it to be /sbin specifically
      (pkgs.runCommand "sbin-ldconfig" {} ''
        mkdir -p $out/sbin
        ln -s /bin/ldconfig $out/sbin/ldconfig
      '')

      # crashes on startup if it can't find libX11 locale files
      (pkgs.runCommand "xorg-locale" {} ''
        mkdir -p $out
        ln -s ${xorg.libX11}/share $out/share
      '')
    ] ++ extraPkgs pkgs;

    # https://gitlab.steamos.cloud/steamrt/steam-runtime-tools/-/blob/main/docs/distro-assumptions.md#shared-libraries
    multiPkgs = pkgs: with pkgs; [
    # These are required by steam with proper errors
    xorg.libXcomposite
    xorg.libXtst
    xorg.libXrandr
    xorg.libXext
    xorg.libX11
    xorg.libXfixes
      glibc
      libxcrypt
      libGL
    libva
    pipewire

    # steamwebhelper
    harfbuzz
    libthai
    pango

    lsof # friends options won't display "Launch Game" without it
    file # called by steam's setup.sh

    # dependencies for mesa drivers, needed inside pressure-vessel
    mesa.llvmPackages.llvm.lib
    vulkan-loader
    expat
    wayland
    xorg.libxcb
    xorg.libXdamage
    xorg.libxshmfence
    xorg.libXxf86vm
    elfutils

    # Without these it silently fails
    xorg.libXinerama
    xorg.libXcursor
    xorg.libXrender
    xorg.libXScrnSaver
    xorg.libXi
    xorg.libSM
    xorg.libICE
    curl
    nspr
    nss
    cups
    libcap
    SDL2
    libusb1
    dbus-glib
    gsettings-desktop-schemas
    ffmpeg
    libudev0-shim

    # Verified games requirements
    fontconfig
    freetype
    xorg.libXt
    xorg.libXmu
    libogg
    libvorbis
    SDL
    SDL2_image
    glew110
      libdrm
    libidn
    tbb
    zlib

    # SteamVR
      mesa  # for libgbm
      udev
    dbus

    # Other things from runtime
    glib
    gtk2
    bzip2
    flac
    libglut
    libjpeg
    libpng
    libpng12
    libsamplerate
    libmikmod
    libtheora
    libtiff
    pixman
    speex
    SDL_image
    SDL_ttf
    SDL_mixer
    SDL2_ttf
    SDL2_mixer
    libappindicator-gtk2
    libdbusmenu-gtk2
    libindicator-gtk2
    libcaca
    libcanberra
    libgcrypt
    libunwind
    libvpx
    librsvg
    xorg.libXft
    libvdpau

    # required by coreutils stuff to run correctly
    # Steam ends up with LD_LIBRARY_PATH=/usr/lib:<bunch of runtime stuff>:<etc>
    # which overrides DT_RUNPATH in our binaries, so it tries to dynload the
    # very old versions of stuff from the runtime.
    # FIXME: how do we even fix this correctly
    attr
    # same thing, but for Xwayland (usually via gamescope), already in the closure
    libkrb5
    keyutils
  ] ++ lib.optionals withGameSpecificLibraries [
    # Not formally in runtime but needed by some games
    at-spi2-atk
    at-spi2-core   # CrossCode
    gst_all_1.gstreamer
    gst_all_1.gst-plugins-ugly
    gst_all_1.gst-plugins-base
    json-glib # paradox launcher (Stellaris)
    libxkbcommon # paradox launcher
    libvorbis # Dead Cells
    libxcrypt # Alien Isolation, XCOM 2, Company of Heroes 2
    mono
    ncurses # Crusader Kings III
    openssl
    xorg.xkeyboardconfig
    xorg.libpciaccess
    xorg.libXScrnSaver # Dead Cells
    icu # dotnet runtime, e.g. Stardew Valley

    # screeps dependencies
    gtk3
    zlib
    atk
    cairo
    gdk-pixbuf

    # Prison Architect
    libGLU
    libuuid
    libbsd
    alsa-lib
      libudev0-shim
      libva
      vulkan-loader

    # Loop Hero
    # FIXME: Also requires openssl_1_1, which is EOL. Either find an alternative solution, or remove these dependencies (if not needed by other games)
    libidn2
    libpsl
    nghttp2.lib
    rtmpdump
  ]
  # This needs to come from pkgs as the passed-in steam-runtime-wrapped may not be the same architecture
  ++ pkgs.steamPackages.steam-runtime-wrapped.overridePkgs
  ++ extraLibraries pkgs;
      networkmanager  # not documented, used for network status things in Big Picture
                      # FIXME: figure out how to only build libnm?
      libcap  # not documented, required by srt-bwrap
    ] ++ extraLibraries pkgs;

    extraInstallCommands = lib.optionalString (steam != null) ''
    mkdir -p $out/share/applications
    ln -s ${steam}/share/icons $out/share
    ln -s ${steam}/share/pixmaps $out/share
    ln -s ${steam}/share/applications/steam.desktop $out/share/applications/steam.desktop
      ln -s ${steam}/share $out/share
    '';

    profile = ''
    # Workaround for issue #44254 (Steam cannot connect to friends network)
    # https://github.com/NixOS/nixpkgs/issues/44254
    if [ -z ''${TZ+x} ]; then
      new_TZ="$(readlink -f /etc/localtime | grep -P -o '(?<=/zoneinfo/).*$')"
      if [ $? -eq 0 ]; then
        export TZ="$new_TZ"
      fi
    fi
      # prevents log spam from SteamRT GTK trying to load host GIO modules
      unset GIO_EXTRA_MODULES

      # udev event notifications don't work reliably inside containers.
      # SDL2 already tries to automatically detect flatpak and pressure-vessel
@@ -264,77 +78,50 @@ in buildFHSEnv rec {
      #
      # [1] <https://github.com/libsdl-org/SDL/commit/8e2746cfb6e1f1a1da5088241a1440fd2535e321>
      export SDL_JOYSTICK_DISABLE_UDEV=1
  '' + extraProfile;

  runScript = writeShellScript "steam-wrapper.sh" ''
    if [ -f /etc/NIXOS ]; then   # Check only useful on NixOS
      ${mesa-demos-i686}/bin/glxinfo 2>&1 | grep -q Error
      # If there was an error running glxinfo, we know something is wrong with the configuration
      if [ $? -eq 0 ]; then
        cat <<EOF > /dev/stderr
    **
    WARNING: Steam is not set up. Add the following options to /etc/nixos/configuration.nix
    and then run \`sudo nixos-rebuild switch\`:
    {
      hardware.graphics.enable32Bit = true;
      hardware.pulseaudio.support32Bit = true;
    }
    **
    EOF
      fi
    fi
      # This is needed for IME (e.g. iBus, fcitx5) to function correctly on non-CJK locales
      # https://github.com/ValveSoftware/steam-for-linux/issues/781#issuecomment-2004757379
      export GTK_IM_MODULE='xim'

    ${exportLDPath}
    ${fixBootstrap}
      # See https://gitlab.steamos.cloud/steamrt/steam-runtime-tools/-/blob/main/docs/distro-assumptions.md#graphics-driver
      export LIBGL_DRIVERS_PATH=/run/opengl-driver/lib/dri:/run/opengl-driver-32/lib/dri
      export __EGL_VENDOR_LIBRARY_DIRS=/run/opengl-driver/share/glvnd/egl_vendor.d:/run/opengl-driver-32/share/glvnd/egl_vendor.d
      export LIBVA_DRIVERS_PATH=/run/opengl-driver/lib/dri:/run/opengl-driver-32/lib/dri
      export VDPAU_DRIVER_PATH=/run/opengl-driver/lib/vdpau:/run/opengl-driver-32/lib/vdpau

    set -o allexport # Export the following env vars
    ${envScript}
    exec steam ${extraArgs} "$@"
      set -a
      ${lib.toShellVars extraEnv}
      set +a

      ${extraProfile}
    '';

  inherit privateTmp;
    privateTmp = true;

  extraPreBwrapCmds = ''
    install -m 1777 -d /tmp/dumps
  '' + args.extraPreBwrapCmds or "";
    inherit extraPreBwrapCmds;

    extraBwrapArgs = [
    "--bind-try /etc/NIXOS /etc/NIXOS" # required 32bit driver check in runScript
      # Steam will dump crash reports here, make those more accessible
      "--bind-try /tmp/dumps /tmp/dumps"
  ] ++ args.extraBwrapArgs or [];

  meta =
    if steam != null
    then
      steam.meta // lib.optionalAttrs (!withGameSpecificLibraries) {
        description = steam.meta.description + " (without game specific libraries)";
        mainProgram = "steam";
      }
    else {
      description = "Steam dependencies (dummy package, do not use)";
    ] ++ extraBwrapArgs;
  };
in steamEnv {
  name = "steam";

  passthru.steamargs = args;
  passthru.run = buildFHSEnv {
    name = "steam-run";
  runScript = writeShellScript "steam-wrapped" ''
    exec steam ${extraArgs} "$@"
  '';

    targetPkgs = commonTargetPkgs;
    inherit multiArch multiPkgs profile extraInstallCommands extraBwrapArgs;
  passthru.run = steamEnv {
    name = "steam-run";

    runScript = writeShellScript "steam-run" ''
      run="$1"
      if [ "$run" = "" ]; then
      if [ $# -eq 0 ]; then
        echo "Usage: steam-run command-to-run args..." >&2
        exit 1
      fi
      shift

      ${exportLDPath}
      ${fixBootstrap}

      set -o allexport # Export the following env vars
      ${envScript}
      exec -- "$run" "$@"
      exec "$@"
    '';

    meta = (steam.meta or {}) // {
@@ -347,4 +134,8 @@ in buildFHSEnv rec {
      license = lib.licenses.mit;
    };
  };

  meta = (steam.meta or {}) // {
    description = "Steam dependencies (dummy package, do not use)";
  };
}
+0 −45
Original line number Diff line number Diff line
{ stdenv, steamArch, lib, perl, pkgs, steam-runtime
, runtimeOnly ? false
}:

let
  overridePkgs = lib.optionals (!runtimeOnly) (with pkgs; [
    libgpg-error
    libpulseaudio
    alsa-lib
    openalSoft
    libva1
    libvdpau
    vulkan-loader
    gcc.cc.lib
    nss
    nspr
    xorg.libxcb
  ]);

  allPkgs = overridePkgs ++ [ steam-runtime ];

  gnuArch = if steamArch == "amd64" then "x86_64-linux-gnu"
            else if steamArch == "i386" then "i386-linux-gnu"
            else throw "Unsupported architecture";

  libs = [ "lib/${gnuArch}" "lib" "usr/lib/${gnuArch}" "usr/lib" ];
  bins = [ "bin" "usr/bin" ];

in stdenv.mkDerivation {
  name = "steam-runtime-wrapped";

  nativeBuildInputs = [ perl ];

  builder = ./build-wrapped.sh;

  passthru = {
    inherit gnuArch libs bins overridePkgs;
    arch = steamArch;
  };

  installPhase = ''
    buildDir "${toString libs}" "${toString (map lib.getLib allPkgs)}"
    buildDir "${toString bins}" "${toString (map lib.getBin allPkgs)}"
  '';
}
Loading