1
0
Fork 0
mirror of https://github.com/nix-community/home-manager synced 2024-11-01 08:49:44 +01:00
home-manager/modules/misc/nixgl.nix
2024-10-25 10:20:38 +02:00

95 lines
3.4 KiB
Nix

{ config, lib, pkgs, ... }:
let cfg = config.nixGL;
in {
meta.maintainers = [ lib.maintainers.smona ];
options.nixGL.prefix = lib.mkOption {
type = lib.types.str;
default = "";
example = lib.literalExpression
''"''${inputs.nixGL.packages.x86_64-linux.nixGLIntel}/bin/nixGLIntel"'';
description = ''
The [nixGL](https://github.com/nix-community/nixGL) command that `lib.nixGL.wrap` should prefix
package binaries with. nixGL provides your system's version of libGL to applications, enabling
them to access the GPU on non-NixOS systems.
Wrap individual packages which require GPU access with the function like so: `(config.lib.nixGL.wrap <package>)`.
The returned package can be used just like the original one, but will have access to libGL. For example:
```nix
# If you're using a Home Manager module to configure the package,
# pass it into the module's package argument:
programs.kitty = {
enable = true;
package = (config.lib.nixGL.wrap pkgs.kitty);
};
# Otherwise, pass it to any option where a package is expected:
home.packages = [ (config.lib.nixGL.wrap pkgs.hello) ];
```
If this option is empty (the default), then `lib.nixGL.wrap` is a no-op. This is useful for sharing your Home Manager
configurations between NixOS and non-NixOS systems, since NixOS already provides libGL to applications without the
need for nixGL.
'';
};
config = {
lib.nixGL.wrap = # Wrap a single package with the configured nixGL wrapper
pkg:
if cfg.prefix == "" then
pkg
else
# Wrap the package's binaries with nixGL, while preserving the rest of
# the outputs and derivation attributes.
(pkg.overrideAttrs (old: {
name = "nixGL-${pkg.name}";
# Make sure this is false for the wrapper derivation, so nix doesn't expect
# a new debug output to be produced. We won't be producing any debug info
# for the original package.
separateDebugInfo = false;
nativeBuildInputs = old.nativeBuildInputs or [ ]
++ [ pkgs.makeWrapper ];
buildCommand = ''
set -eo pipefail
${
# Heavily inspired by https://stackoverflow.com/a/68523368/6259505
lib.concatStringsSep "\n" (map (outputName: ''
echo "Copying output ${outputName}"
set -x
cp -rs --no-preserve=mode "${
pkg.${outputName}
}" "''$${outputName}"
set +x
'') (old.outputs or [ "out" ]))}
rm -rf $out/bin/*
shopt -s nullglob # Prevent loop from running if no files
for file in ${pkg.out}/bin/*; do
local prog="$(basename "$file")"
makeWrapper \
"${cfg.prefix}" \
"$out/bin/$prog" \
--argv0 "$prog" \
--add-flags "$file"
done
# If .desktop files refer to the old package, replace the references
for dsk in "$out/share/applications"/*.desktop ; do
if ! grep -q "${pkg.out}" "$dsk"; then
continue
fi
src="$(readlink "$dsk")"
rm "$dsk"
sed "s|${pkg.out}|$out|g" "$src" > "$dsk"
done
shopt -u nullglob # Revert nullglob back to its normal default state
'';
}));
};
}