diff --git a/doc/default.nix b/doc/default.nix index f4270ae856d5..58b945c692fc 100644 --- a/doc/default.nix +++ b/doc/default.nix @@ -21,6 +21,7 @@ let { name = "filesystem"; description = "filesystem functions"; } { name = "sources"; description = "source filtering functions"; } { name = "cli"; description = "command-line serialization functions"; } + { name = "gvariant"; description = "GVariant formatted string serialization functions"; } ]; }; diff --git a/lib/default.nix b/lib/default.nix index 136f4a4a4637..509636452b2b 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -41,6 +41,7 @@ let # serialization cli = callLibs ./cli.nix; + gvariant = callLibs ./gvariant.nix; generators = callLibs ./generators.nix; # misc diff --git a/lib/generators.nix b/lib/generators.nix index c37be1942d82..0368577d5a51 100644 --- a/lib/generators.nix +++ b/lib/generators.nix @@ -230,6 +230,14 @@ rec { in toINI_ (gitFlattenAttrs attrs); + # mkKeyValueDefault wrapper that handles dconf INI quirks. + # The main differences of the format is that it requires strings to be quoted. + mkDconfKeyValue = mkKeyValueDefault { mkValueString = v: toString (lib.gvariant.mkValue v); } "="; + + # Generates INI in dconf keyfile style. See https://help.gnome.org/admin/system-admin-guide/stable/dconf-keyfiles.html.en + # for details. + toDconfINI = toINI { mkKeyValue = mkDconfKeyValue; }; + /* Generates JSON from an arbitrary (non-function) value. * For more information see the documentation of the builtin. */ diff --git a/lib/gvariant.nix b/lib/gvariant.nix new file mode 100644 index 000000000000..3142ffc5f149 --- /dev/null +++ b/lib/gvariant.nix @@ -0,0 +1,290 @@ +# This file is based on https://github.com/nix-community/home-manager +# Copyright (c) 2017-2022 Home Manager contributors +# + + +{ lib }: + +/* A partial and basic implementation of GVariant formatted strings. + See https://docs.gtk.org/glib/gvariant-format-strings.html for detauls. + + Note, this API is not considered fully stable and it might therefore + change in backwards incompatible ways without prior notice. +*/ +let + inherit (lib) + concatMapStringsSep concatStrings escape head replaceStrings; + + mkPrimitive = t: v: { + _type = "gvariant"; + type = t; + value = v; + __toString = self: "@${self.type} ${toString self.value}"; # https://docs.gtk.org/glib/gvariant-text.html + }; + + type = { + arrayOf = t: "a${t}"; + maybeOf = t: "m${t}"; + tupleOf = ts: "(${concatStrings ts})"; + dictionaryEntryOf = nameType: valueType: "{${nameType}${valueType}}"; + string = "s"; + boolean = "b"; + uchar = "y"; + int16 = "n"; + uint16 = "q"; + int32 = "i"; + uint32 = "u"; + int64 = "x"; + uint64 = "t"; + double = "d"; + variant = "v"; + }; + + /* Check if a value is a GVariant value + + Type: + isGVariant :: Any -> Bool + */ + isGVariant = v: v._type or "" == "gvariant"; + +in +rec { + + inherit type isGVariant; + + /* Returns the GVariant value that most closely matches the given Nix value. + If no GVariant value can be found unambiguously then error is thrown. + + Type: + mkValue :: Any -> gvariant + */ + mkValue = v: + if builtins.isBool v then + mkBoolean v + else if builtins.isFloat v then + mkDouble v + else if builtins.isString v then + mkString v + else if builtins.isList v then + mkArray v + else if isGVariant v then + v + else + throw "The GVariant type of ${v} can't be inferred."; + + /* Returns the GVariant array from the given type of the elements and a Nix list. + + Type: + mkArray :: [Any] -> gvariant + + Example: + # Creating a string array + lib.gvariant.mkArray [ "a" "b" "c" ] + */ + mkArray = elems: + let + vs = map mkValue (lib.throwIf (elems == [ ]) "Please create empty array with mkEmptyArray." elems); + elemType = lib.throwIfNot (lib.all (t: (head vs).type == t) (map (v: v.type) vs)) + "Elements in a list should have same type." + (head vs).type; + in + mkPrimitive (type.arrayOf elemType) vs // { + __toString = self: + "@${self.type} [${concatMapStringsSep "," toString self.value}]"; + }; + + /* Returns the GVariant array from the given empty Nix list. + + Type: + mkEmptyArray :: gvariant.type -> gvariant + + Example: + # Creating an empty string array + lib.gvariant.mkEmptyArray (lib.gvariant.type.string) + */ + mkEmptyArray = elemType: mkPrimitive (type.arrayOf elemType) [ ] // { + __toString = self: "@${self.type} []"; + }; + + + /* Returns the GVariant variant from the given Nix value. Variants are containers + of different GVariant type. + + Type: + mkVariant :: Any -> gvariant + + Example: + lib.gvariant.mkArray [ + (lib.gvariant.mkVariant "a string") + (lib.gvariant.mkVariant (lib.gvariant.mkInt32 1)) + ] + */ + mkVariant = elem: + let gvarElem = mkValue elem; + in mkPrimitive type.variant gvarElem // { + __toString = self: "<${toString self.value}>"; + }; + + /* Returns the GVariant dictionary entry from the given key and value. + + Type: + mkDictionaryEntry :: String -> Any -> gvariant + + Example: + # A dictionary describing an Epiphany’s search provider + [ + (lib.gvariant.mkDictionaryEntry "url" (lib.gvariant.mkVariant "https://duckduckgo.com/?q=%s&t=epiphany")) + (lib.gvariant.mkDictionaryEntry "bang" (lib.gvariant.mkVariant "!d")) + (lib.gvariant.mkDictionaryEntry "name" (lib.gvariant.mkVariant "DuckDuckGo")) + ] + */ + mkDictionaryEntry = + # The key of the entry + name: + # The value of the entry + value: + let + name' = mkValue name; + value' = mkValue value; + dictionaryType = type.dictionaryEntryOf name'.type value'.type; + in + mkPrimitive dictionaryType { inherit name value; } // { + __toString = self: "@${self.type} {${name'},${value'}}"; + }; + + /* Returns the GVariant maybe from the given element type. + + Type: + mkMaybe :: gvariant.type -> Any -> gvariant + */ + mkMaybe = elemType: elem: + mkPrimitive (type.maybeOf elemType) elem // { + __toString = self: + if self.value == null then + "@${self.type} nothing" + else + "just ${toString self.value}"; + }; + + /* Returns the GVariant nothing from the given element type. + + Type: + mkNothing :: gvariant.type -> gvariant + */ + mkNothing = elemType: mkMaybe elemType null; + + /* Returns the GVariant just from the given Nix value. + + Type: + mkJust :: Any -> gvariant + */ + mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem; + + /* Returns the GVariant tuple from the given Nix list. + + Type: + mkTuple :: [Any] -> gvariant + */ + mkTuple = elems: + let + gvarElems = map mkValue elems; + tupleType = type.tupleOf (map (e: e.type) gvarElems); + in + mkPrimitive tupleType gvarElems // { + __toString = self: + "@${self.type} (${concatMapStringsSep "," toString self.value})"; + }; + + /* Returns the GVariant boolean from the given Nix bool value. + + Type: + mkBoolean :: Bool -> gvariant + */ + mkBoolean = v: + mkPrimitive type.boolean v // { + __toString = self: if self.value then "true" else "false"; + }; + + /* Returns the GVariant string from the given Nix string value. + + Type: + mkString :: String -> gvariant + */ + mkString = v: + let sanitize = s: replaceStrings [ "\n" ] [ "\\n" ] (escape [ "'" "\\" ] s); + in mkPrimitive type.string v // { + __toString = self: "'${sanitize self.value}'"; + }; + + /* Returns the GVariant object path from the given Nix string value. + + Type: + mkObjectpath :: String -> gvariant + */ + mkObjectpath = v: + mkPrimitive type.string v // { + __toString = self: "objectpath '${escape [ "'" ] self.value}'"; + }; + + /* Returns the GVariant uchar from the given Nix int value. + + Type: + mkUchar :: Int -> gvariant + */ + mkUchar = mkPrimitive type.uchar; + + /* Returns the GVariant int16 from the given Nix int value. + + Type: + mkInt16 :: Int -> gvariant + */ + mkInt16 = mkPrimitive type.int16; + + /* Returns the GVariant uint16 from the given Nix int value. + + Type: + mkUint16 :: Int -> gvariant + */ + mkUint16 = mkPrimitive type.uint16; + + /* Returns the GVariant int32 from the given Nix int value. + + Type: + mkInt32 :: Int -> gvariant + */ + mkInt32 = v: + mkPrimitive type.int32 v // { + __toString = self: toString self.value; + }; + + /* Returns the GVariant uint32 from the given Nix int value. + + Type: + mkUint32 :: Int -> gvariant + */ + mkUint32 = mkPrimitive type.uint32; + + /* Returns the GVariant int64 from the given Nix int value. + + Type: + mkInt64 :: Int -> gvariant + */ + mkInt64 = mkPrimitive type.int64; + + /* Returns the GVariant uint64 from the given Nix int value. + + Type: + mkUint64 :: Int -> gvariant + */ + mkUint64 = mkPrimitive type.uint64; + + /* Returns the GVariant double from the given Nix float value. + + Type: + mkDouble :: Float -> gvariant + */ + mkDouble = v: + mkPrimitive type.double v // { + __toString = self: toString self.value; + }; +} diff --git a/lib/tests/modules/gvariant.nix b/lib/tests/modules/gvariant.nix new file mode 100644 index 000000000000..a792ebf85b74 --- /dev/null +++ b/lib/tests/modules/gvariant.nix @@ -0,0 +1,93 @@ +{ config, lib, ... }: + +let inherit (lib) concatStringsSep mapAttrsToList mkMerge mkOption types gvariant; +in { + options.examples = mkOption { type = types.attrsOf gvariant; }; + + config = { + examples = with gvariant; + mkMerge [ + { bool = true; } + { bool = true; } + + { float = 3.14; } + + { int32 = mkInt32 (- 42); } + { int32 = mkInt32 (- 42); } + + { uint32 = mkUint32 42; } + { uint32 = mkUint32 42; } + + { int16 = mkInt16 (-42); } + { int16 = mkInt16 (-42); } + + { uint16 = mkUint16 42; } + { uint16 = mkUint16 42; } + + { int64 = mkInt64 (-42); } + { int64 = mkInt64 (-42); } + + { uint64 = mkUint64 42; } + { uint64 = mkUint64 42; } + + { array1 = [ "one" ]; } + { array1 = mkArray [ "two" ]; } + { array2 = mkArray [ (mkInt32 1) ]; } + { array2 = mkArray [ (nkUint32 2) ]; } + + { emptyArray1 = [ ]; } + { emptyArray2 = mkEmptyArray type.uint32; } + + { string = "foo"; } + { string = "foo"; } + { + escapedString = '' + '\ + ''; + } + + { tuple = mkTuple [ (mkInt32 1) [ "foo" ] ]; } + + { maybe1 = mkNothing type.string; } + { maybe2 = mkJust (mkUint32 4); } + + { variant1 = mkVariant "foo"; } + { variant2 = mkVariant 42; } + + { dictionaryEntry = mkDictionaryEntry (mkInt32 1) [ "foo" ]; } + ]; + + assertions = [ + { + assertion = ( + let + mkLine = n: v: "${n} = ${toString (gvariant.mkValue v)}"; + result = concatStringsSep "\n" (mapAttrsToList mkLine config.examples); + in + result + "\n" + ) == '' + array1 = @as ['one','two'] + array2 = @au [1,2] + bool = true + dictionaryEntry = @{ias} {1,@as ['foo']} + emptyArray1 = @as [] + emptyArray2 = @au [] + escapedString = '\'\\\n' + float = 3.140000 + int = -42 + int16 = @n -42 + int64 = @x -42 + maybe1 = @ms nothing + maybe2 = just @u 4 + string = 'foo' + tuple = @(ias) (1,@as ['foo']) + uint16 = @q 42 + uint32 = @u 42 + uint64 = @t 42 + variant1 = @v <'foo'> + variant2 = @v <42> + ''; + } + ]; + }; +} diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index edfe43e350ed..32be7642f4b0 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -13888,6 +13888,16 @@ githubId = 33375; name = "Peter Sanford"; }; + pschmitt = { + email = "philipp@schmitt.co"; + github = "pschmitt"; + githubId = 37886; + name = "Philipp Schmitt"; + matrix = "@pschmitt:one.ems.host"; + keys = [{ + fingerprint = "9FBF 2ABF FB37 F7F3 F502 44E5 DC43 9C47 EACB 17F9"; + }]; + }; pshirshov = { email = "pshirshov@eml.cc"; github = "pshirshov"; @@ -18631,6 +18641,12 @@ github = "XYenon"; githubId = 20698483; }; + xyven1 = { + name = "Xyven"; + email = "nix@xyven.dev"; + github = "xyven1"; + githubId = 35360746; + }; xzfc = { email = "xzfcpw@gmail.com"; github = "xzfc"; diff --git a/nixos/modules/programs/dconf.nix b/nixos/modules/programs/dconf.nix index 7261a143528f..cf53658c4fad 100644 --- a/nixos/modules/programs/dconf.nix +++ b/nixos/modules/programs/dconf.nix @@ -1,55 +1,217 @@ { config, lib, pkgs, ... }: -with lib; - let cfg = config.programs.dconf; - cfgDir = pkgs.symlinkJoin { - name = "dconf-system-config"; - paths = map (x: "${x}/etc/dconf") cfg.packages; - postBuild = '' - mkdir -p $out/profile - mkdir -p $out/db - '' + ( - concatStringsSep "\n" ( - mapAttrsToList ( - name: path: '' - ln -s ${path} $out/profile/${name} - '' - ) cfg.profiles - ) - ) + '' - ${pkgs.dconf}/bin/dconf update $out/db - ''; + + # Compile keyfiles to dconf DB + compileDconfDb = dir: pkgs.runCommand "dconf-db" + { + nativeBuildInputs = [ (lib.getBin pkgs.dconf) ]; + } "dconf compile $out ${dir}"; + + # Check if dconf keyfiles are valid + checkDconfKeyfiles = dir: pkgs.runCommand "check-dconf-keyfiles" + { + nativeBuildInputs = [ (lib.getBin pkgs.dconf) ]; + } '' + if [[ -f ${dir} ]]; then + echo "dconf keyfiles should be a directory but a file is provided: ${dir}" + exit 1 + fi + + dconf compile db ${dir} || ( + echo "The dconf keyfiles are invalid: ${dir}" + exit 1 + ) + cp -R ${dir} $out + ''; + + mkAllLocks = settings: lib.flatten ( + lib.mapAttrsToList (k: v: lib.mapAttrsToList (k': _: "/${k}/${k'}") v) settings); + + # Generate dconf DB from dconfDatabase and keyfiles + mkDconfDb = val: compileDconfDb (pkgs.symlinkJoin { + name = "nixos-generated-dconf-keyfiles"; + paths = [ + (pkgs.writeTextDir "nixos-generated-dconf-keyfiles" (lib.generators.toDconfINI val.settings)) + (pkgs.writeTextDir "locks/nixos-generated-dconf-locks" (lib.concatStringsSep "\n" + (if val.lockAll then mkAllLocks val.settings else val.locks) + )) + ] ++ (map checkDconfKeyfiles val.keyfiles); + }); + + # Check if a dconf DB file is valid. The dconf cli doesn't return 1 when it can't + # open the database file so we have to check if the output is empty. + checkDconfDb = file: pkgs.runCommand "check-dconf-db" + { + nativeBuildInputs = [ (lib.getBin pkgs.dconf) ]; + } '' + if [[ -d ${file} ]]; then + echo "dconf DB should be a file but a directory is provided: ${file}" + exit 1 + fi + + echo "file-db:${file}" > profile + DCONF_PROFILE=$(pwd)/profile dconf dump / > output 2> error + if [[ ! -s output ]] && [[ -s error ]]; then + cat error + echo "The dconf DB file is invalid: ${file}" + exit 1 + fi + + cp ${file} $out + ''; + + # Generate dconf profile + mkDconfProfile = name: value: + if lib.isDerivation value || lib.isPath value then + pkgs.runCommand "dconf-profile" { } '' + if [[ -d ${value} ]]; then + echo "Dconf profile should be a file but a directory is provided." + exit 1 + fi + mkdir -p $out/etc/dconf/profile/ + cp ${value} $out/etc/dconf/profile/${name} + '' + else + pkgs.writeTextDir "etc/dconf/profile/${name}" ( + lib.concatMapStrings (x: "${x}\n") (( + lib.optional value.enableUserDb "user-db:user" + ) ++ ( + map + (value: + let + db = if lib.isAttrs value && !lib.isDerivation value then mkDconfDb value else checkDconfDb value; + in + "file-db:${db}") + value.databases + )) + ); + + dconfDatabase = with lib.types; submodule { + options = { + keyfiles = lib.mkOption { + type = listOf (oneOf [ path package ]); + default = [ ]; + description = lib.mdDoc "A list of dconf keyfile directories."; + }; + settings = lib.mkOption { + type = attrs; + default = { }; + description = lib.mdDoc "An attrset used to generate dconf keyfile."; + example = literalExpression '' + with lib.gvariant; + { + "com/raggesilver/BlackBox" = { + scrollback-lines = mkUint32 10000; + theme-dark = "Tommorow Night"; + }; + } + ''; + }; + locks = lib.mkOption { + type = with lib.types; listOf str; + default = [ ]; + description = lib.mdDoc '' + A list of dconf keys to be lockdown. This doesn't take effect if `lockAll` + is set. + ''; + example = literalExpression '' + [ "/org/gnome/desktop/background/picture-uri" ] + ''; + }; + lockAll = lib.mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc "Lockdown all dconf keys in `settings`."; + }; + }; }; -in -{ - ###### interface - options = { - programs.dconf = { - enable = mkEnableOption (lib.mdDoc "dconf"); - - profiles = mkOption { - type = types.attrsOf types.path; - default = {}; - description = lib.mdDoc "Set of dconf profile files, installed at {file}`/etc/dconf/profiles/«name»`."; - internal = true; + dconfProfile = with lib.types; submodule { + options = { + enableUserDb = lib.mkOption { + type = bool; + default = true; + description = lib.mdDoc "Add `user-db:user` at the beginning of the profile."; }; - packages = mkOption { - type = types.listOf types.package; - default = []; + databases = lib.mkOption { + type = with lib.types; listOf (oneOf [ + path + package + dconfDatabase + ]); + default = [ ]; + description = lib.mdDoc '' + List of data sources for the profile. An element can be an attrset, + or the path of an already compiled database. Each element is converted + to a file-db. + + A key is searched from up to down and the first result takes the + priority. If a lock for a particular key is installed then the value from + the last database in the profile where the key is locked will be used. + This can be used to enforce mandatory settings. + ''; + }; + }; + }; + +in +{ + options = { + programs.dconf = { + enable = lib.mkEnableOption (lib.mdDoc "dconf"); + + profiles = lib.mkOption { + type = with lib.types; attrsOf (oneOf [ + path + package + dconfProfile + ]); + default = { }; + description = lib.mdDoc '' + Attrset of dconf profiles. By default the `user` profile is used which + ends up in `/etc/dconf/profile/user`. + ''; + example = lib.literalExpression '' + { + # A "user" profile with a database + user.databases = [ + { + settings = { }; + } + ]; + # A "bar" profile from a package + bar = pkgs.bar-dconf-profile; + # A "foo" profile from a path + foo = ''${./foo} + }; + ''; + }; + + packages = lib.mkOption { + type = lib.types.listOf lib.types.package; + default = [ ]; description = lib.mdDoc "A list of packages which provide dconf profiles and databases in {file}`/etc/dconf`."; }; }; }; - ###### implementation + config = lib.mkIf (cfg.profiles != { } || cfg.enable) { + programs.dconf.packages = lib.mapAttrsToList mkDconfProfile cfg.profiles; - config = mkIf (cfg.profiles != {} || cfg.enable) { - environment.etc.dconf = mkIf (cfg.profiles != {} || cfg.packages != []) { - source = cfgDir; + environment.etc.dconf = lib.mkIf (cfg.packages != [ ]) { + source = pkgs.symlinkJoin { + name = "dconf-system-config"; + paths = map (x: "${x}/etc/dconf") cfg.packages; + nativeBuildInputs = [ (lib.getBin pkgs.dconf) ]; + postBuild = '' + if test -d $out/db; then + dconf update $out/db + fi + ''; + }; }; services.dbus.packages = [ pkgs.dconf ]; @@ -59,8 +221,9 @@ in # For dconf executable environment.systemPackages = [ pkgs.dconf ]; - # Needed for unwrapped applications - environment.sessionVariables.GIO_EXTRA_MODULES = mkIf cfg.enable [ "${pkgs.dconf.lib}/lib/gio/modules" ]; + environment.sessionVariables = lib.mkIf cfg.enable { + # Needed for unwrapped applications + GIO_EXTRA_MODULES = [ "${pkgs.dconf.lib}/lib/gio/modules" ]; + }; }; - } diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix index 676d08b93e2c..e6923bcbb56c 100644 --- a/nixos/modules/services/x11/display-managers/gdm.nix +++ b/nixos/modules/services/x11/display-managers/gdm.nix @@ -231,40 +231,14 @@ in systemd.user.services.dbus.wantedBy = [ "default.target" ]; - programs.dconf.profiles.gdm = - let - customDconf = pkgs.writeTextFile { - name = "gdm-dconf"; - destination = "/dconf/gdm-custom"; - text = '' - ${optionalString (!cfg.gdm.autoSuspend) '' - [org/gnome/settings-daemon/plugins/power] - sleep-inactive-ac-type='nothing' - sleep-inactive-battery-type='nothing' - sleep-inactive-ac-timeout=0 - sleep-inactive-battery-timeout=0 - ''} - ''; + programs.dconf.profiles.gdm.databases = lib.optionals (!cfg.gdm.autoSuspend) [{ + settings."org/gnome/settings-daemon/plugins/power" = { + sleep-inactive-ac-type = "nothing"; + sleep-inactive-battery-type = "nothing"; + sleep-inactive-ac-timeout = lib.gvariant.mkInt32 0; + sleep-inactive-battery-timeout = lib.gvariant.mkInt32 0; }; - - customDconfDb = pkgs.stdenv.mkDerivation { - name = "gdm-dconf-db"; - buildCommand = '' - ${pkgs.dconf}/bin/dconf compile $out ${customDconf}/dconf - ''; - }; - in pkgs.stdenv.mkDerivation { - name = "dconf-gdm-profile"; - buildCommand = '' - # Check that the GDM profile starts with what we expect. - if [ $(head -n 1 ${gdm}/share/dconf/profile/gdm) != "user-db:user" ]; then - echo "GDM dconf profile changed, please update gdm.nix" - exit 1 - fi - # Insert our custom DB behind it. - sed '2ifile-db:${customDconfDb}' ${gdm}/share/dconf/profile/gdm > $out - ''; - }; + }] ++ [ "${gdm}/share/gdm/greeter-dconf-defaults" ]; # Use AutomaticLogin if delay is zero, because it's immediate. # Otherwise with TimedLogin with zero seconds the prompt is still diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index bef18a90775c..c1e124bda5c7 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -210,6 +210,7 @@ in { custom-ca = handleTest ./custom-ca.nix {}; croc = handleTest ./croc.nix {}; darling = handleTest ./darling.nix {}; + dconf = handleTest ./dconf.nix {}; deepin = handleTest ./deepin.nix {}; deluge = handleTest ./deluge.nix {}; dendrite = handleTest ./matrix/dendrite.nix {}; diff --git a/nixos/tests/dconf.nix b/nixos/tests/dconf.nix new file mode 100644 index 000000000000..86f703e3b98e --- /dev/null +++ b/nixos/tests/dconf.nix @@ -0,0 +1,34 @@ +import ./make-test-python.nix + ({ lib, ... }: + { + name = "dconf"; + + meta.maintainers = with lib.maintainers; [ + linsui + ]; + + nodes.machine = { config, pkgs, lib, ... }: { + users.extraUsers.alice = { isNormalUser = true; }; + programs.dconf = with lib.gvariant; { + enable = true; + profiles.user.databases = [ + { + settings = { + "test/not/locked" = mkInt32 1; + "test/is/locked" = "locked"; + }; + locks = [ + "/test/is/locked" + ]; + } + ]; + }; + }; + + testScript = '' + machine.succeed("test $(dconf read -d /test/not/locked) == 1") + machine.succeed("test $(dconf read -d /test/is/locked) == \"'locked'\"") + machine.fail("sudo -u alice dbus-run-session -- dconf write /test/is/locked \"@s 'unlocked'\"") + machine.succeed("sudo -u alice dbus-run-session -- dconf write /test/not/locked \"@i 2\"") + ''; + }) diff --git a/pkgs/applications/audio/spotify-player/default.nix b/pkgs/applications/audio/spotify-player/default.nix index 4c5417ab99fc..963cbe3252ea 100644 --- a/pkgs/applications/audio/spotify-player/default.nix +++ b/pkgs/applications/audio/spotify-player/default.nix @@ -4,12 +4,30 @@ , pkg-config , openssl , cmake +# deps for audio backends , alsa-lib +, libpulseaudio +, portaudio +, libjack2 +, SDL2 +, gst_all_1 , dbus , fontconfig , libsixel + +# build options +, withStreaming ? true +, withDaemon ? true +, withAudioBackend ? "rodio" # alsa, pulseaudio, rodio, portaudio, jackaudio, rodiojack, sdl +, withMediaControl ? true +, withLyrics ? true +, withImage ? true +, withNotify ? true +, withSixel ? true }: +assert lib.assertOneOf "withAudioBackend" withAudioBackend [ "" "alsa" "pulseaudio" "rodio" "portaudio" "jackaudio" "rodiojack" "sdl" "gstreamer" ]; + rustPlatform.buildRustPackage rec { pname = "spotify-player"; version = "0.15.0"; @@ -30,31 +48,37 @@ rustPlatform.buildRustPackage rec { buildInputs = [ openssl - alsa-lib dbus fontconfig - libsixel - ]; + ] + ++ lib.optionals withSixel [ libsixel ] + ++ lib.optionals (withAudioBackend == "alsa") [ alsa-lib ] + ++ lib.optionals (withAudioBackend == "pulseaudio") [ libpulseaudio ] + ++ lib.optionals (withAudioBackend == "rodio") [ alsa-lib ] + ++ lib.optionals (withAudioBackend == "portaudio") [ portaudio ] + ++ lib.optionals (withAudioBackend == "jackaudio") [ libjack2 ] + ++ lib.optionals (withAudioBackend == "rodiojack") [ alsa-lib libjack2 ] + ++ lib.optionals (withAudioBackend == "sdl") [ SDL2 ] + ++ lib.optionals (withAudioBackend == "gstreamer") [ gst_all_1.gstreamer gst_all_1.gst-devtools gst_all_1.gst-plugins-base gst_all_1.gst-plugins-good ]; buildNoDefaultFeatures = true; - buildFeatures = [ - "rodio-backend" - "media-control" - "image" - "lyric-finder" - "daemon" - "notify" - "streaming" - "sixel" - ]; + buildFeatures = [ ] + ++ lib.optionals (withAudioBackend != "") [ "${withAudioBackend}-backend" ] + ++ lib.optionals withMediaControl [ "media-control" ] + ++ lib.optionals withImage [ "image" ] + ++ lib.optionals withLyrics [ "lyric-finder" ] + ++ lib.optionals withDaemon [ "daemon" ] + ++ lib.optionals withNotify [ "notify" ] + ++ lib.optionals withStreaming [ "streaming" ] + ++ lib.optionals withSixel [ "sixel" ]; - meta = with lib; { - description = "A command driven spotify player"; + meta = { + description = "A terminal spotify player that has feature parity with the official client"; homepage = "https://github.com/aome510/spotify-player"; changelog = "https://github.com/aome510/spotify-player/releases/tag/v${version}"; mainProgram = "spotify_player"; - license = licenses.mit; - maintainers = with maintainers; [ dit7ya ]; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ dit7ya xyven1 ]; }; } diff --git a/pkgs/applications/editors/emacs/site-start.el b/pkgs/applications/editors/emacs/site-start.el index acc6833b98c9..b0694a90af0e 100644 --- a/pkgs/applications/editors/emacs/site-start.el +++ b/pkgs/applications/editors/emacs/site-start.el @@ -8,8 +8,11 @@ least specific (the system profile)" ;;; Extend `load-path' to search for elisp files in subdirectories of all folders in `NIX_PROFILES'. ;;; Non-Nix distros have similar logic in /usr/share/emacs/site-lisp/subdirs.el. ;;; See https://www.gnu.org/software/emacs/manual/html_node/elisp/Library-Search.html -(dolist (profile (nix--profile-paths)) - (let ((default-directory (expand-file-name "share/emacs/site-lisp/" profile))) +(dolist (profile (reverse (nix--profile-paths))) + ;; `directory-file-name' is important to add sub dirs to the right place of `load-path' + ;; see the source code of `normal-top-level-add-to-load-path' + (let ((default-directory (directory-file-name + (expand-file-name "share/emacs/site-lisp/" profile)))) (when (file-exists-p default-directory) (setq load-path (cons default-directory load-path)) (normal-top-level-add-subdirs-to-load-path)))) @@ -37,13 +40,19 @@ least specific (the system profile)" (mapconcat 'identity new-env-list ":")))))) ;;; Set up native-comp load path. -(when (featurep 'comp) +(when (featurep 'native-compile) ;; Append native-comp subdirectories from `NIX_PROFILES'. + ;; Emacs writes asynchronous native-compilation files to the first writable directory[1]. + ;; At this time, (car native-comp-eln-load-path) is a writable one in `user-emacs-directory'[2]. + ;; So we keep that one unchanged. + ;; [1]: info "(elisp) Native-Compilation Variables" + ;; [2]: https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/startup.el?id=3685387e609753293c4518be75e77c659c3b2d8d#n601 (setq native-comp-eln-load-path - (append (mapcar (lambda (profile-dir) + (append (list (car native-comp-eln-load-path)) + (mapcar (lambda (profile-dir) (concat profile-dir "/share/emacs/native-lisp/")) (nix--profile-paths)) - native-comp-eln-load-path))) + (cdr native-comp-eln-load-path)))) ;;; Make `woman' find the man pages (defvar woman-manpath) diff --git a/pkgs/applications/kde/colord-kde.nix b/pkgs/applications/kde/colord-kde.nix index 07f34c84d6f1..7b3c783995c6 100644 --- a/pkgs/applications/kde/colord-kde.nix +++ b/pkgs/applications/kde/colord-kde.nix @@ -1,8 +1,8 @@ { mkDerivation, lib , extra-cmake-modules, ki18n -, kconfig, kconfigwidgets, kcoreaddons, kdbusaddons, kiconthemes, kcmutils -, kio, knotifications, plasma-framework, kwidgetsaddons, kwindowsystem -, kitemmodels, kitemviews, lcms2, libXrandr, qtx11extras +, kconfig, kconfigwidgets, kcoreaddons, kdbusaddons, kiconthemes, kirigami-addons +, kcmutils, kio, knotifications, plasma-framework, kwidgetsaddons +, kwindowsystem, kitemmodels, kitemviews, lcms2, libXrandr, qtx11extras }: mkDerivation { @@ -11,7 +11,7 @@ mkDerivation { nativeBuildInputs = [ extra-cmake-modules ]; buildInputs = [ - kconfig kconfigwidgets kcoreaddons kdbusaddons kiconthemes + kconfig kconfigwidgets kcoreaddons kdbusaddons kiconthemes kirigami-addons kcmutils ki18n kio knotifications plasma-framework kwidgetsaddons kwindowsystem kitemmodels kitemviews lcms2 libXrandr qtx11extras ]; diff --git a/pkgs/applications/networking/cluster/krane/Gemfile.lock b/pkgs/applications/networking/cluster/krane/Gemfile.lock index cf5832b24dc0..5a930bf2c99e 100644 --- a/pkgs/applications/networking/cluster/krane/Gemfile.lock +++ b/pkgs/applications/networking/cluster/krane/Gemfile.lock @@ -1,19 +1,19 @@ GEM remote: https://rubygems.org/ specs: - activesupport (7.0.4.3) + activesupport (7.0.7.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - addressable (2.8.4) + addressable (2.8.5) public_suffix (>= 2.0.2, < 6.0) colorize (0.8.1) concurrent-ruby (1.2.2) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - ejson (1.3.1) - faraday (2.7.4) + ejson (1.4.1) + faraday (2.7.10) faraday-net_http (>= 2.0, < 3.1) ruby2_keywords (>= 0.0.4) faraday-net_http (3.0.2) @@ -21,7 +21,7 @@ GEM ffi-compiler (1.0.1) ffi (>= 1.0.0) rake - googleauth (1.5.2) + googleauth (1.7.0) faraday (>= 0.17.3, < 3.a) jwt (>= 1.4, < 3.0) memoist (~> 0.16) @@ -37,12 +37,12 @@ GEM http-cookie (1.0.5) domain_name (~> 0.5) http-form_data (2.3.0) - i18n (1.12.0) + i18n (1.14.1) concurrent-ruby (~> 1.0) - jsonpath (1.1.2) + jsonpath (1.1.3) multi_json - jwt (2.7.0) - krane (3.1.0) + jwt (2.7.1) + krane (3.3.0) activesupport (>= 5.0) colorize (~> 0.8) concurrent-ruby (~> 1.1) @@ -50,7 +50,7 @@ GEM googleauth (~> 1.2) jsonpath (~> 1.0) kubeclient (~> 4.9) - oj (~> 3.0) + multi_json statsd-instrument (>= 2.8, < 4) thor (>= 1.0, < 2.0) kubeclient (4.11.0) @@ -62,15 +62,14 @@ GEM ffi-compiler (~> 1.0) rake (~> 13.0) memoist (0.16.2) - mime-types (3.4.1) + mime-types (3.5.1) mime-types-data (~> 3.2015) - mime-types-data (3.2023.0218.1) - minitest (5.18.0) + mime-types-data (3.2023.0808) + minitest (5.19.0) multi_json (1.15.0) netrc (0.11.0) - oj (3.14.3) os (1.1.4) - public_suffix (5.0.1) + public_suffix (5.0.3) rake (13.0.6) recursive-open-struct (1.1.3) rest-client (2.1.0) @@ -84,8 +83,8 @@ GEM faraday (>= 0.17.5, < 3.a) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) - statsd-instrument (3.5.7) - thor (1.2.1) + statsd-instrument (3.5.11) + thor (1.2.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unf (0.1.4) @@ -99,4 +98,4 @@ DEPENDENCIES krane BUNDLED WITH - 2.4.10 + 2.4.18 diff --git a/pkgs/applications/networking/cluster/krane/gemset.nix b/pkgs/applications/networking/cluster/krane/gemset.nix index 37fad5926869..50c859eb7223 100644 --- a/pkgs/applications/networking/cluster/krane/gemset.nix +++ b/pkgs/applications/networking/cluster/krane/gemset.nix @@ -5,10 +5,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "15m0b1im6i401ab51vzr7f8nk8kys1qa0snnl741y3sir3xd07jp"; + sha256 = "1vlzcnyqlbchaq85phmdv73ydlc18xpvxy1cbsk191cwd29i7q32"; type = "gem"; }; - version = "7.0.4.3"; + version = "7.0.7.2"; }; addressable = { dependencies = ["public_suffix"]; @@ -16,10 +16,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "15s8van7r2ad3dq6i03l3z4hqnvxcq75a3h72kxvf9an53sqma20"; + sha256 = "05r1fwy487klqkya7vzia8hnklcxy4vr92m9dmni3prfwk6zpw33"; type = "gem"; }; - version = "2.8.4"; + version = "2.8.5"; }; colorize = { groups = ["default"]; @@ -57,10 +57,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0gmfyyzzvb9k5nm1a5x83d7krajfghghfsakhxmdpvncyj2vnrpa"; + sha256 = "1bpry4i9ajh2h8fyljp0cb17iy03ar36yc9mpfxflmdznl7dwsjf"; type = "gem"; }; - version = "1.3.1"; + version = "1.4.1"; }; faraday = { dependencies = ["faraday-net_http" "ruby2_keywords"]; @@ -68,10 +68,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1f20vjx0ywx0zdb4dfx4cpa7kd51z6vg7dw5hs35laa45dy9g9pj"; + sha256 = "187clqhp9mv5mnqmjlfdp57svhsg1bggz84ak8v333j9skrnrgh9"; type = "gem"; }; - version = "2.7.4"; + version = "2.7.10"; }; faraday-net_http = { groups = ["default"]; @@ -110,10 +110,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1lj5haarpn7rybbq9s031zcn9ji3rlz5bk64bwa2j34q5s1h5gis"; + sha256 = "0h1k47vjaq37l0w9q49g3f50j1b0c1svhk07rmd1h49w38v2hxag"; type = "gem"; }; - version = "1.5.2"; + version = "1.7.0"; }; http = { dependencies = ["addressable" "http-cookie" "http-form_data" "llhttp-ffi"]; @@ -163,10 +163,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1vdcchz7jli1p0gnc669a7bj3q1fv09y9ppf0y3k0vb1jwdwrqwi"; + sha256 = "0qaamqsh5f3szhcakkak8ikxlzxqnv49n2p7504hcz2l0f4nj0wx"; type = "gem"; }; - version = "1.12.0"; + version = "1.14.1"; }; jsonpath = { dependencies = ["multi_json"]; @@ -174,31 +174,31 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0fkdjic88hh0accp0sbx5mcrr9yaqwampf5c3214212d4i614138"; + sha256 = "1i1idcl0rpfkzkxngadw33a33v3gqf93a3kj52y2ha2zs26bdzjp"; type = "gem"; }; - version = "1.1.2"; + version = "1.1.3"; }; jwt = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "09yj3z5snhaawh2z1w45yyihzmh57m6m7dp8ra8gxavhj5kbiq5p"; + sha256 = "16z11alz13vfc4zs5l3fk6n51n2jw9lskvc4h4prnww0y797qd87"; type = "gem"; }; - version = "2.7.0"; + version = "2.7.1"; }; krane = { - dependencies = ["activesupport" "colorize" "concurrent-ruby" "ejson" "googleauth" "jsonpath" "kubeclient" "oj" "statsd-instrument" "thor"]; + dependencies = ["activesupport" "colorize" "concurrent-ruby" "ejson" "googleauth" "jsonpath" "kubeclient" "multi_json" "statsd-instrument" "thor"]; groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1d8vdj3wd2qp8agyadn0w33qf7z2p5lk3vlslb8jlph8x5y3mm70"; + sha256 = "1qf5la1w4zrbda5n3s01pb9gij5hyknwglsnqsrc0vcm6bslfygj"; type = "gem"; }; - version = "3.1.0"; + version = "3.3.0"; }; kubeclient = { dependencies = ["http" "jsonpath" "recursive-open-struct" "rest-client"]; @@ -238,30 +238,30 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0ipw892jbksbxxcrlx9g5ljq60qx47pm24ywgfbyjskbcl78pkvb"; + sha256 = "0q8d881k1b3rbsfcdi3fx0b5vpdr5wcrhn88r2d9j7zjdkxp5mw5"; type = "gem"; }; - version = "3.4.1"; + version = "3.5.1"; }; mime-types-data = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1pky3vzaxlgm9gw5wlqwwi7wsw3jrglrfflrppvvnsrlaiz043z9"; + sha256 = "17zdim7kzrh5j8c97vjqp4xp78wbyz7smdp4hi5iyzk0s9imdn5a"; type = "gem"; }; - version = "3.2023.0218.1"; + version = "3.2023.0808"; }; minitest = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0ic7i5z88zcaqnpzprf7saimq2f6sad57g5mkkqsrqrcd6h3mx06"; + sha256 = "0jnpsbb2dbcs95p4is4431l2pw1l5pn7dfg3vkgb4ga464j0c5l6"; type = "gem"; }; - version = "5.18.0"; + version = "5.19.0"; }; multi_json = { groups = ["default"]; @@ -283,16 +283,6 @@ }; version = "0.11.0"; }; - oj = { - groups = ["default"]; - platforms = []; - source = { - remotes = ["https://rubygems.org"]; - sha256 = "0l8l90iibzrxs33vn3adrhbg8cbmbn1qfh962p7gzwwybsdw73qy"; - type = "gem"; - }; - version = "3.14.3"; - }; os = { groups = ["default"]; platforms = []; @@ -308,10 +298,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0hz0bx2qs2pwb0bwazzsah03ilpf3aai8b7lk7s35jsfzwbkjq35"; + sha256 = "0n9j7mczl15r3kwqrah09cxj8hxdfawiqxa60kga2bmxl9flfz9k"; type = "gem"; }; - version = "5.0.1"; + version = "5.0.3"; }; rake = { groups = ["default"]; @@ -370,20 +360,20 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1pg308z3ck1vpazrmczklqa6f9qciay8nysnhc16pgfsh2npzzrz"; + sha256 = "1zpr5ms18ynygpwx73v0a8nkf41kpjylc9m3fyhvchq3ms17hcb0"; type = "gem"; }; - version = "3.5.7"; + version = "3.5.11"; }; thor = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0inl77jh4ia03jw3iqm5ipr76ghal3hyjrd6r8zqsswwvi9j2xdi"; + sha256 = "0k7j2wn14h1pl4smibasw0bp66kg626drxb59z7rzflch99cd4rg"; type = "gem"; }; - version = "1.2.1"; + version = "1.2.2"; }; tzinfo = { dependencies = ["concurrent-ruby"]; diff --git a/pkgs/applications/networking/mailreaders/betterbird/default.nix b/pkgs/applications/networking/mailreaders/betterbird/default.nix index d08bd5dfcc4a..9c63f3f37cad 100644 --- a/pkgs/applications/networking/mailreaders/betterbird/default.nix +++ b/pkgs/applications/networking/mailreaders/betterbird/default.nix @@ -12,13 +12,13 @@ let thunderbird-unwrapped = thunderbirdPackages.thunderbird-102; - version = "102.12.0"; + version = "102.14.0"; majVer = lib.versions.major version; betterbird-patches = fetchFromGitHub { owner = "Betterbird"; repo = "thunderbird-patches"; - rev = "${version}-bb37"; + rev = "${version}-bb39"; postFetch = '' echo "Retrieving external patches" @@ -36,7 +36,7 @@ let . ./external.sh rm external.sh ''; - sha256 = "sha256-LH0dgWqariutfaOCPIUZrHzZ8oCbZF1VaaKQIQS4aL8="; + hash = "sha256-O9nGlJs3OziQLbdbdt3eFRHvk1A9cdEsbKDtsZrnY5Q="; }; in ((buildMozillaMach { pname = "betterbird"; @@ -49,7 +49,7 @@ in ((buildMozillaMach { src = fetchurl { # https://download.cdn.mozilla.net/pub/thunderbird/releases/ url = "mirror://mozilla/thunderbird/releases/${version}/source/thunderbird-${version}.source.tar.xz"; - sha512 = "303787a8f22a204e48784d54320d5f4adaeeeedbe4c2294cd26ad75792272ffc9453be7f0ab1434214b61a2cc46982c23c4fd447c4d80d588df4a7800225ddee"; + sha512 = "4ae3f216833aec55421f827d55bc1b5fc2f0ad4fefecb27724a5be3318c351df24d30a4897b924e733ed2e3995be284b6d135049d46001143fb1c961fefc1830"; }; extraPostPatch = thunderbird-unwrapped.extraPostPatch or "" + /* bash */ '' diff --git a/pkgs/applications/office/vnote/default.nix b/pkgs/applications/office/vnote/default.nix index ef77a0778250..cd118c3c1d88 100644 --- a/pkgs/applications/office/vnote/default.nix +++ b/pkgs/applications/office/vnote/default.nix @@ -10,14 +10,14 @@ stdenv.mkDerivation (finalAttrs: { pname = "vnote"; - version = "3.16.0"; + version = "3.17.0"; src = fetchFromGitHub { owner = "vnotex"; repo = "vnote"; rev = "v${finalAttrs.version}"; fetchSubmodules = true; - hash = "sha256-tcu6y2DqdhFE2nbDkiANDk/Mzidcp8PLi8bWZaI6sH0="; + hash = "sha256-NUVu6tKXrrwAoT4BgxX05mmGSC9yx20lwvXzd4y19Zs="; }; nativeBuildInputs = [ diff --git a/pkgs/applications/video/obs-studio/plugins/default.nix b/pkgs/applications/video/obs-studio/plugins/default.nix index 086f6285a5ed..63bad0fe6459 100644 --- a/pkgs/applications/video/obs-studio/plugins/default.nix +++ b/pkgs/applications/video/obs-studio/plugins/default.nix @@ -20,6 +20,8 @@ obs-command-source = callPackage ./obs-command-source.nix { }; + obs-freeze-filter = qt6Packages.callPackage ./obs-freeze-filter.nix { }; + obs-gradient-source = callPackage ./obs-gradient-source.nix { }; obs-gstreamer = callPackage ./obs-gstreamer.nix { }; diff --git a/pkgs/applications/video/obs-studio/plugins/obs-freeze-filter.nix b/pkgs/applications/video/obs-studio/plugins/obs-freeze-filter.nix new file mode 100644 index 000000000000..1460e77fbf86 --- /dev/null +++ b/pkgs/applications/video/obs-studio/plugins/obs-freeze-filter.nix @@ -0,0 +1,40 @@ +{ stdenv +, lib +, fetchFromGitHub +, cmake +, obs-studio +, qtbase +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "obs-freeze-filter"; + version = "0.3.3"; + + src = fetchFromGitHub { + owner = "exeldro"; + repo = "obs-freeze-filter"; + rev = finalAttrs.version; + sha256 = "sha256-CaHBTfdk8VFjmiclG61elj35glQafgz5B4ENo+7J35o="; + fetchSubmodules = true; + }; + + nativeBuildInputs = [ cmake ]; + buildInputs = [ obs-studio qtbase ]; + + postInstall = '' + rm -rf "$out/share" + mkdir -p "$out/share/obs" + mv "$out/data/obs-plugins" "$out/share/obs" + rm -rf "$out/obs-plugins" "$out/data" + ''; + + dontWrapQtApps = true; + + meta = with lib; { + description = "Plugin for OBS Studio to freeze a source using a filter"; + homepage = "https://github.com/exeldro/obs-freeze-filter"; + license = licenses.gpl2Only; + platforms = platforms.linux; + maintainers = with maintainers; [ pschmitt ]; + }; +}) diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index c7c733a427aa..f52ac48a1a87 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -69,7 +69,7 @@ let includeFortifyHeaders' = if includeFortifyHeaders != null then includeFortifyHeaders - else targetPlatform.libc == "musl"; + else (targetPlatform.libc == "musl" && isGNU); # Prefix for binaries. Customarily ends with a dash separator. # diff --git a/pkgs/build-support/emacs/wrapper.nix b/pkgs/build-support/emacs/wrapper.nix index e3c67d03dfa1..6f46bb692a43 100644 --- a/pkgs/build-support/emacs/wrapper.nix +++ b/pkgs/build-support/emacs/wrapper.nix @@ -159,12 +159,10 @@ runCommand rm -f $siteStart $siteStartByteCompiled $subdirs $subdirsByteCompiled cat >"$siteStart" <