1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
|
{ 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:
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
# 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;
targetPkgs = pkgs: with pkgs; [
steam
# License agreement
zenity
] ++ commonTargetPkgs pkgs;
multiPkgs = pkgs: with pkgs; [
# These are required by steam with proper errors
xorg.libXcomposite
xorg.libXtst
xorg.libXrandr
xorg.libXext
xorg.libX11
xorg.libXfixes
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
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
# 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;
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
'';
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
# udev event notifications don't work reliably inside containers.
# SDL2 already tries to automatically detect flatpak and pressure-vessel
# and falls back to inotify-based discovery [1]. We make SDL2 do the
# same by telling it explicitly.
#
# [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
${exportLDPath}
${fixBootstrap}
set -o allexport # Export the following env vars
${envScript}
exec steam ${extraArgs} "$@"
'';
inherit privateTmp;
extraPreBwrapCmds = ''
install -m 1777 -d /tmp/dumps
'' + args.extraPreBwrapCmds or "";
extraBwrapArgs = [
"--bind-try /etc/NIXOS /etc/NIXOS" # required 32bit driver check in runScript
"--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)";
};
passthru.steamargs = args;
passthru.run = buildFHSEnv {
name = "steam-run";
targetPkgs = commonTargetPkgs;
inherit multiArch multiPkgs profile extraInstallCommands extraBwrapArgs;
runScript = writeShellScript "steam-run" ''
run="$1"
if [ "$run" = "" ]; 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" "$@"
'';
meta = (steam.meta or {}) // {
description = "Run commands in the same FHS environment that is used for Steam";
mainProgram = "steam-run";
name = "steam-run";
# steam-run itself is just a script that lives in nixpkgs (which is licensed under MIT).
# steam is a dependency and already unfree, so normal steam-run will not install without
# allowing unfree packages or appropriate `allowUnfreePredicate` rules.
license = lib.licenses.mit;
};
};
}
|