about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/attrsets.nix9
-rw-r--r--lib/composable-derivation.nix113
-rw-r--r--lib/default.nix16
-rw-r--r--lib/deprecated.nix126
-rw-r--r--lib/fixed-points.nix10
-rw-r--r--lib/licenses.nix61
-rw-r--r--lib/meta.nix11
-rw-r--r--lib/modules.nix34
-rw-r--r--lib/strings.nix20
-rw-r--r--lib/systems/default.nix2
-rw-r--r--lib/systems/examples.nix6
-rw-r--r--lib/systems/parse.nix13
-rw-r--r--lib/tests/misc.nix38
-rwxr-xr-xlib/tests/modules.sh6
-rw-r--r--lib/tests/modules/alias-with-priority-can-override.nix52
-rw-r--r--lib/tests/modules/alias-with-priority.nix52
16 files changed, 228 insertions, 341 deletions
diff --git a/lib/attrsets.nix b/lib/attrsets.nix
index 2a1b866dbc5e..d374d229f597 100644
--- a/lib/attrsets.nix
+++ b/lib/attrsets.nix
@@ -94,6 +94,15 @@ rec {
   attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs);
 
 
+  /* Given a set of attribute names, return the set of the corresponding
+     attributes from the given set.
+
+     Example:
+       getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
+       => { a = 1; b = 2; }
+  */
+  getAttrs = names: attrs: genAttrs names (name: attrs.${name});
+
   /* Collect each attribute named `attr' from a list of attribute
      sets.  Sets that don't contain the named attribute are ignored.
 
diff --git a/lib/composable-derivation.nix b/lib/composable-derivation.nix
deleted file mode 100644
index cb1fdc121e11..000000000000
--- a/lib/composable-derivation.nix
+++ /dev/null
@@ -1,113 +0,0 @@
-{lib, pkgs}:
-let inherit (lib) nvs; in
-{
-
-  # composableDerivation basically mixes these features:
-  # - fix function
-  # - mergeAttrBy
-  # - provides shortcuts for "options" such as "--enable-foo" and adding
-  #   buildInputs, see php example
-  #
-  # It predates styles which are common today, such as
-  #  * the config attr
-  #  * mkDerivation.override feature
-  #  * overrideDerivation (lib/customization.nix)
-  #
-  # Some of the most more important usage examples (which could be rewritten if it was important):
-  # * php
-  # * postgis
-  # * vim_configurable
-  #
-  # A minimal example illustrating most features would look like this:
-  # let base = composableDerivation { (fixed: let inherit (fixed.fixed) name in {
-  #    src = fetchurl {
-  #    }
-  #    buildInputs = [A];
-  #    preConfigre = "echo ${name}";
-  #    # attention, "name" attr is missing, thus you cannot instantiate "base".
-  # }
-  # in {
-  #  # These all add name attribute, thus you can instantiate those:
-  #  v1 = base.merge   ({ name = "foo-add-B"; buildInputs = [B]; });       // B gets merged into buildInputs
-  #  v2 = base.merge   ({ name = "mix-in-pre-configure-lines" preConfigre = ""; });
-  #  v3 = base.replace ({ name = "foo-no-A-only-B;" buildInputs = [B]; });
-  # }
-  #
-  # So yes, you can think about it being something like nixos modules, and
-  # you'd be merging "features" in one at a time using .merge or .replace
-  # Thanks Shea for telling me that I rethink the documentation ..
-  #
-  # issues:
-  # * its complicated to understand
-  # * some "features" such as exact merge behaviour are buried in mergeAttrBy
-  #   and defaultOverridableDelayableArgs assuming the default behaviour does
-  #   the right thing in the common case
-  # * Eelco once said using such fix style functions are slow to evaluate
-  # * Too quick & dirty. Hard to understand for others. The benefit was that
-  #   you were able to create a kernel builder like base derivation and replace
-  #   / add patches the way you want without having to declare function arguments
-  #
-  # nice features:
-  # declaring "optional features" is modular. For instance:
-  #   flags.curl = {
-  #     configureFlags = ["--with-curl=${curl.dev}" "--with-curlwrappers"];
-  #     buildInputs = [curl openssl];
-  #   };
-  #   flags.other = { .. }
-  # (Example taken from PHP)
-  #
-  # alternative styles / related features:
-  #  * Eg see function supporting building the kernel
-  #  * versionedDerivation (discussion about this is still going on - or ended)
-  #  * composedArgsAndFun
-  #  * mkDerivation.override
-  #  * overrideDerivation
-  #  * using { .., *Support ? false }: like configurable options.
-  # To find those examples use grep
-  #
-  # To sum up: It exists for historical reasons - and for most commonly used
-  # tasks the alternatives should be used
-  #
-  # If you have questions about this code ping Marc Weber.
-  composableDerivation = {
-        mkDerivation ? pkgs.stdenv.mkDerivation,
-
-        # list of functions to be applied before defaultOverridableDelayableArgs removes removeAttrs names
-        # prepareDerivationArgs handles derivation configurations
-        applyPreTidy ? [ lib.prepareDerivationArgs ],
-
-        # consider adding addtional elements by derivation.merge { removeAttrs = ["elem"]; };
-        removeAttrs ? ["cfg" "flags"]
-
-      }: (lib.defaultOverridableDelayableArgs ( a: mkDerivation a)
-         {
-           inherit applyPreTidy removeAttrs;
-         }).merge;
-
-  # some utility functions
-  # use this function to generate flag attrs for prepareDerivationArgs
-  # E nable  D isable F eature
-  edf = {name, feat ? name, enable ? {}, disable ? {} , value ? ""}:
-    nvs name {
-    set = {
-      configureFlags = ["--enable-${feat}${if value == "" then "" else "="}${value}"];
-    } // enable;
-    unset = {
-      configureFlags = ["--disable-${feat}"];
-    } // disable;
-  };
-
-  # same for --with and --without-
-  # W ith or W ithout F eature
-  wwf = {name, feat ? name, enable ? {}, disable ? {}, value ? ""}:
-    nvs name {
-    set = enable // {
-      configureFlags = ["--with-${feat}${if value == "" then "" else "="}${value}"]
-                       ++ lib.maybeAttr "configureFlags" [] enable;
-    };
-    unset = disable // {
-      configureFlags = ["--without-${feat}"]
-                       ++ lib.maybeAttr "configureFlags" [] disable;
-    };
-  };
-}
diff --git a/lib/default.nix b/lib/default.nix
index d7a05fec8338..d400907ebb0c 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -61,10 +61,10 @@ let
       boolToString mergeAttrs flip mapNullable inNixShell min max
       importJSON warn info nixpkgsVersion version mod compare
       splitByAndCompare functionArgs setFunctionArgs isFunction;
-    inherit (fixedPoints) fix fix' extends composeExtensions
+    inherit (fixedPoints) fix fix' converge extends composeExtensions
       makeExtensible makeExtensibleWithCustomName;
     inherit (attrsets) attrByPath hasAttrByPath setAttrByPath
-      getAttrFromPath attrVals attrValues catAttrs filterAttrs
+      getAttrFromPath attrVals attrValues getAttrs catAttrs filterAttrs
       filterAttrsRecursive foldAttrs collect nameValuePair mapAttrs
       mapAttrs' mapAttrsToList mapAttrsRecursive mapAttrsRecursiveCond
       genAttrs isDerivation toDerivation optionalAttrs
@@ -80,7 +80,7 @@ let
     inherit (strings) concatStrings concatMapStrings concatImapStrings
       intersperse concatStringsSep concatMapStringsSep
       concatImapStringsSep makeSearchPath makeSearchPathOutput
-      makeLibraryPath makeBinPath makePerlPath makeFullPerlPath optionalString
+      makeLibraryPath makeBinPath optionalString
       hasPrefix hasSuffix stringToCharacters stringAsChars escape
       escapeShellArg escapeShellArgs replaceChars lowerChars
       upperChars toLower toUpper addContextFrom splitString
@@ -94,7 +94,7 @@ let
       callPackageWith callPackagesWith extendDerivation hydraJob
       makeScope;
     inherit (meta) addMetaAttrs dontDistribute setName updateName
-      appendToName mapDerivationAttrset lowPrio lowPrioSet hiPrio
+      appendToName mapDerivationAttrset setPrio lowPrio lowPrioSet hiPrio
       hiPrioSet;
     inherit (sources) pathType pathIsDirectory cleanSourceFilter
       cleanSource sourceByRegex sourceFilesBySuffices
@@ -109,7 +109,7 @@ let
       mkFixStrictness mkOrder mkBefore mkAfter mkAliasDefinitions
       mkAliasAndWrapDefinitions fixMergeModules mkRemovedOptionModule
       mkRenamedOptionModule mkMergedOptionModule mkChangedOptionModule
-      mkAliasOptionModule doRename filterModules;
+      mkAliasOptionModule mkAliasOptionModuleWithPriority doRename filterModules;
     inherit (options) isOption mkEnableOption mkSinkUndeclaredOptions
       mergeDefaultOption mergeOneOption mergeEqualOption getValues
       getFiles optionAttrSetToDocList optionAttrSetToDocList'
@@ -125,14 +125,14 @@ let
       traceShowValMarked showVal traceCall traceCall2 traceCall3
       traceValIfNot runTests testAllTrue traceCallXml attrNamesToStr;
     inherit (misc) maybeEnv defaultMergeArg defaultMerge foldArgs
-      defaultOverridableDelayableArgs composedArgsAndFun
       maybeAttrNullable maybeAttr ifEnable checkFlag getValue
       checkReqs uniqList uniqListExt condConcat lazyGenericClosure
       innerModifySumArgs modifySumArgs innerClosePropagation
       closePropagation mapAttrsFlatten nvs setAttr setAttrMerge
       mergeAttrsWithFunc mergeAttrsConcatenateValues
       mergeAttrsNoOverride mergeAttrByFunc mergeAttrsByFuncDefaults
-      mergeAttrsByFuncDefaultsClean mergeAttrBy prepareDerivationArgs
-      nixType imap overridableDelayableArgs;
+      mergeAttrsByFuncDefaultsClean mergeAttrBy
+      fakeSha256 fakeSha512
+      nixType imap;
   });
 in lib
diff --git a/lib/deprecated.nix b/lib/deprecated.nix
index 34cf336d1f42..15de50456612 100644
--- a/lib/deprecated.nix
+++ b/lib/deprecated.nix
@@ -35,74 +35,6 @@ rec {
           withStdOverrides;
 
 
-  # predecessors: proposed replacement for applyAndFun (which has a bug cause it merges twice)
-  # the naming "overridableDelayableArgs" tries to express that you can
-  # - override attr values which have been supplied earlier
-  # - use attr values before they have been supplied by accessing the fix point
-  #   name "fixed"
-  # f: the (delayed overridden) arguments are applied to this
-  #
-  # initial: initial attrs arguments and settings. see defaultOverridableDelayableArgs
-  #
-  # returns: f applied to the arguments // special attributes attrs
-  #     a) merge: merge applied args with new args. Wether an argument is overridden depends on the merge settings
-  #     b) replace: this let's you replace and remove names no matter which merge function has been set
-  #
-  # examples: see test cases "res" below;
-  overridableDelayableArgs =
-          f:        # the function applied to the arguments
-          initial:  # you pass attrs, the functions below are passing a function taking the fix argument
-    let
-        takeFixed = if lib.isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
-        tidy = args:
-            let # apply all functions given in "applyPreTidy" in sequence
-                applyPreTidyFun = fold ( n: a: x: n ( a x ) ) lib.id (maybeAttr "applyPreTidy" [] args);
-            in removeAttrs (applyPreTidyFun args) ( ["applyPreTidy"] ++ (maybeAttr  "removeAttrs" [] args) ); # tidy up args before applying them
-        fun = n: x:
-            let newArgs = fixed:
-                    let args = takeFixed fixed;
-                        mergeFun = args.${n};
-                    in if isAttrs x then (mergeFun args x)
-                       else assert lib.isFunction x;
-                            mergeFun args (x ( args // { inherit fixed; }));
-            in overridableDelayableArgs f newArgs;
-    in
-    (f (tidy (lib.fix takeFixed))) // {
-      merge   = fun "mergeFun";
-      replace = fun "keepFun";
-    };
-  defaultOverridableDelayableArgs = f:
-      let defaults = {
-            mergeFun = mergeAttrByFunc; # default merge function. merge strategie (concatenate lists, strings) is given by mergeAttrBy
-            keepFun = a: b: { inherit (a) removeAttrs mergeFun keepFun mergeAttrBy; } // b; # even when using replace preserve these values
-            applyPreTidy = []; # list of functions applied to args before args are tidied up (usage case : prepareDerivationArgs)
-            mergeAttrBy = mergeAttrBy // {
-              applyPreTidy = a: b: a ++ b;
-              removeAttrs = a: b: a ++ b;
-            };
-            removeAttrs = ["mergeFun" "keepFun" "mergeAttrBy" "removeAttrs" "fixed" ]; # before applying the arguments to the function make sure these names are gone
-          };
-      in (overridableDelayableArgs f defaults).merge;
-
-
-
-  # rec { # an example of how composedArgsAndFun can be used
-  #  a  = composedArgsAndFun (x: x) { a = ["2"]; meta = { d = "bar";}; };
-  #  # meta.d will be lost ! It's your task to preserve it (eg using a merge function)
-  #  b  = a.passthru.function { a = [ "3" ]; meta = { d2 = "bar2";}; };
-  #  # instead of passing/ overriding values you can use a merge function:
-  #  c  = b.passthru.function ( x: { a = x.a  ++ ["4"]; }); # consider using (maybeAttr "a" [] x)
-  # }
-  # result:
-  # {
-  #   a = { a = ["2"];     meta = { d = "bar"; }; passthru = { function = .. }; };
-  #   b = { a = ["3"];     meta = { d2 = "bar2"; }; passthru = { function = .. }; };
-  #   c = { a = ["3" "4"]; meta = { d2 = "bar2"; }; passthru = { function = .. }; };
-  #   # c2 is equal to c
-  # }
-  composedArgsAndFun = f: foldArgs defaultMerge f {};
-
-
   # shortcut for attrByPath ["name"] default attrs
   maybeAttrNullable = maybeAttr;
 
@@ -285,7 +217,7 @@ rec {
   # };
   # will result in
   # { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
-  # is used by prepareDerivationArgs, defaultOverridableDelayableArgs and can be used when composing using
+  # is used by defaultOverridableDelayableArgs and can be used when composing using
   # foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
   mergeAttrByFunc = x: y:
     let
@@ -318,58 +250,6 @@ rec {
     // listToAttrs (map (n: nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ])
   ;
 
-  # prepareDerivationArgs tries to make writing configurable derivations easier
-  # example:
-  #  prepareDerivationArgs {
-  #    mergeAttrBy = {
-  #       myScript = x: y: x ++ "\n" ++ y;
-  #    };
-  #    cfg = {
-  #      readlineSupport = true;
-  #    };
-  #    flags = {
-  #      readline = {
-  #        set = {
-  #           configureFlags = [ "--with-compiler=${compiler}" ];
-  #           buildInputs = [ compiler ];
-  #           pass = { inherit compiler; READLINE=1; };
-  #           assertion = compiler.dllSupport;
-  #           myScript = "foo";
-  #        };
-  #        unset = { configureFlags = ["--without-compiler"]; };
-  #      };
-  #    };
-  #    src = ...
-  #    buildPhase = '' ... '';
-  #    name = ...
-  #    myScript = "bar";
-  #  };
-  # if you don't have need for unset you can omit the surrounding set = { .. } attr
-  # all attrs except flags cfg and mergeAttrBy will be merged with the
-  # additional data from flags depending on config settings
-  # It's used in composableDerivation in all-packages.nix. It's also used
-  # heavily in the new python and libs implementation
-  #
-  # should we check for misspelled cfg options?
-  # TODO use args.mergeFun here as well?
-  prepareDerivationArgs = args:
-    let args2 = { cfg = {}; flags = {}; } // args;
-        flagName = name: "${name}Support";
-        cfgWithDefaults = (listToAttrs (map (n: nameValuePair (flagName n) false) (attrNames args2.flags)))
-                          // args2.cfg;
-        opts = attrValues (mapAttrs (a: v:
-                let v2 = if v ? set || v ? unset then v else { set = v; };
-                    n = if cfgWithDefaults.${flagName a} then "set" else "unset";
-                    attr = maybeAttr n {} v2; in
-                if (maybeAttr "assertion" true attr)
-                  then attr
-                  else throw "assertion of flag ${a} of derivation ${args.name} failed"
-               ) args2.flags );
-    in removeAttrs
-      (mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }]))
-      ["flags" "cfg" "mergeAttrBy" ];
-
-
   nixType = x:
       if isAttrs x then
           if x ? outPath then "derivation"
@@ -390,4 +270,8 @@ rec {
      starting at zero.
   */
   imap = imap1;
+
+  # Fake hashes. Can be used as hash placeholders, when computing hash ahead isn't trivial
+  fakeSha256 = "0000000000000000000000000000000000000000000000000000000000000000";
+  fakeSha512 = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
 }
diff --git a/lib/fixed-points.nix b/lib/fixed-points.nix
index 7169c46fcbbc..2f818c88de5d 100644
--- a/lib/fixed-points.nix
+++ b/lib/fixed-points.nix
@@ -24,6 +24,16 @@ rec {
   # for a concrete example.
   fix' = f: let x = f x // { __unfix__ = f; }; in x;
 
+  # Return the fixpoint that `f` converges to when called recursively, starting
+  # with the input `x`.
+  #
+  #     nix-repl> converge (x: x / 2) 16
+  #     0
+  converge = f: x:
+    if (f x) == x
+    then x
+    else converge f (f x);
+
   # Modify the contents of an explicitly recursive attribute set in a way that
   # honors `self`-references. This is accomplished with a function
   #
diff --git a/lib/licenses.nix b/lib/licenses.nix
index ed91b5adedbf..fc9cb42621d4 100644
--- a/lib/licenses.nix
+++ b/lib/licenses.nix
@@ -29,13 +29,13 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
   };
 
   agpl3 = spdx {
-    spdxId = "AGPL-3.0";
-    fullName = "GNU Affero General Public License v3.0";
+    spdxId = "AGPL-3.0-only";
+    fullName = "GNU Affero General Public License v3.0 only";
   };
 
-  agpl3Plus = {
+  agpl3Plus = spdx {
+    spdxId = "AGPL-3.0-or-later";
     fullName = "GNU Affero General Public License v3.0 or later";
-    inherit (agpl3) url;
   };
 
   amazonsl = {
@@ -266,13 +266,23 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
   };
 
   fdl12 = spdx {
-    spdxId = "GFDL-1.2";
-    fullName = "GNU Free Documentation License v1.2";
+    spdxId = "GFDL-1.2-only";
+    fullName = "GNU Free Documentation License v1.2 only";
+  };
+
+  fdl12Plus = spdx {
+    spdxId = "GFDL-1.2-or-later";
+    fullName = "GNU Free Documentation License v1.2 or later";
   };
 
   fdl13 = spdx {
-    spdxId = "GFDL-1.3";
-    fullName = "GNU Free Documentation License v1.3";
+    spdxId = "GFDL-1.3-only";
+    fullName = "GNU Free Documentation License v1.3 only";
+  };
+
+  fdl13Plus = spdx {
+    spdxId = "GFDL-1.3-or-later";
+    fullName = "GNU Free Documentation License v1.3 or later";
   };
 
   ffsl = {
@@ -297,24 +307,23 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
   };
 
   gpl1 = spdx {
-    spdxId = "GPL-1.0";
+    spdxId = "GPL-1.0-only";
     fullName = "GNU General Public License v1.0 only";
   };
 
   gpl1Plus = spdx {
-    spdxId = "GPL-1.0+";
+    spdxId = "GPL-1.0-or-later";
     fullName = "GNU General Public License v1.0 or later";
   };
 
   gpl2 = spdx {
-    spdxId = "GPL-2.0";
+    spdxId = "GPL-2.0-only";
     fullName = "GNU General Public License v2.0 only";
   };
 
-  gpl2Classpath = {
+  gpl2Classpath = spdx {
     spdxId = "GPL-2.0-with-classpath-exception";
     fullName = "GNU General Public License v2.0 only (with Classpath exception)";
-    url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
   };
 
   gpl2ClasspathPlus = {
@@ -328,17 +337,17 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
   };
 
   gpl2Plus = spdx {
-    spdxId = "GPL-2.0+";
+    spdxId = "GPL-2.0-or-later";
     fullName = "GNU General Public License v2.0 or later";
   };
 
   gpl3 = spdx {
-    spdxId = "GPL-3.0";
+    spdxId = "GPL-3.0-only";
     fullName = "GNU General Public License v3.0 only";
   };
 
   gpl3Plus = spdx {
-    spdxId = "GPL-3.0+";
+    spdxId = "GPL-3.0-or-later";
     fullName = "GNU General Public License v3.0 or later";
   };
 
@@ -408,32 +417,32 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
   };
 
   lgpl2 = spdx {
-    spdxId = "LGPL-2.0";
+    spdxId = "LGPL-2.0-only";
     fullName = "GNU Library General Public License v2 only";
   };
 
   lgpl2Plus = spdx {
-    spdxId = "LGPL-2.0+";
+    spdxId = "LGPL-2.0-or-later";
     fullName = "GNU Library General Public License v2 or later";
   };
 
   lgpl21 = spdx {
-    spdxId = "LGPL-2.1";
+    spdxId = "LGPL-2.1-only";
     fullName = "GNU Library General Public License v2.1 only";
   };
 
   lgpl21Plus = spdx {
-    spdxId = "LGPL-2.1+";
+    spdxId = "LGPL-2.1-or-later";
     fullName = "GNU Library General Public License v2.1 or later";
   };
 
   lgpl3 = spdx {
-    spdxId = "LGPL-3.0";
+    spdxId = "LGPL-3.0-only";
     fullName = "GNU Lesser General Public License v3.0 only";
   };
 
   lgpl3Plus = spdx {
-    spdxId = "LGPL-3.0+";
+    spdxId = "LGPL-3.0-or-later";
     fullName = "GNU Lesser General Public License v3.0 or later";
   };
 
@@ -505,6 +514,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
     free = false;
   };
 
+  nasa13 = spdx {
+    spdxId = "NASA-1.3";
+    fullName = "NASA Open Source Agreement 1.3";
+    free = false;
+  };
+
   ncsa = spdx {
     spdxId = "NCSA";
     fullName  = "University of Illinois/NCSA Open Source License";
@@ -691,7 +706,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
   };
 
   wxWindows = spdx {
-    spdxId = "WXwindows";
+    spdxId = "wxWindows";
     fullName = "wxWindows Library Licence, Version 3.1";
   };
 
diff --git a/lib/meta.nix b/lib/meta.nix
index 199030c103af..2e83c4247ddf 100644
--- a/lib/meta.nix
+++ b/lib/meta.nix
@@ -41,16 +41,18 @@ rec {
     let x = builtins.parseDrvName name; in "${x.name}-${suffix}-${x.version}");
 
 
-  /* Apply a function to each derivation and only to derivations in an attrset
+  /* Apply a function to each derivation and only to derivations in an attrset.
   */
   mapDerivationAttrset = f: set: lib.mapAttrs (name: pkg: if lib.isDerivation pkg then (f pkg) else pkg) set;
 
+  /* Set the nix-env priority of the package.
+  */
+  setPrio = priority: addMetaAttrs { inherit priority; };
 
   /* Decrease the nix-env priority of the package, i.e., other
      versions/variants of the package will be preferred.
   */
-  lowPrio = drv: addMetaAttrs { priority = 10; } drv;
-
+  lowPrio = setPrio 10;
 
   /* Apply lowPrio to an attrset with derivations
   */
@@ -60,8 +62,7 @@ rec {
   /* Increase the nix-env priority of the package, i.e., this
      version/variant of the package will be preferred.
   */
-  hiPrio = drv: addMetaAttrs { priority = -10; } drv;
-
+  hiPrio = setPrio (-10);
 
   /* Apply hiPrio to an attrset with derivations
   */
diff --git a/lib/modules.nix b/lib/modules.nix
index 5fb83a4a538c..9f8e196ee0f7 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -450,8 +450,7 @@ rec {
 
   filterOverrides' = defs:
     let
-      defaultPrio = 100;
-      getPrio = def: if def.value._type or "" == "override" then def.value.priority else defaultPrio;
+      getPrio = def: if def.value._type or "" == "override" then def.value.priority else defaultPriority;
       highestPrio = foldl' (prio: def: min (getPrio def) prio) 9999 defs;
       strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def;
     in {
@@ -534,6 +533,8 @@ rec {
   mkBefore = mkOrder 500;
   mkAfter = mkOrder 1500;
 
+  # The default priority for things that don't have a priority specified.
+  defaultPriority = 100;
 
   # Convenient property used to transfer all definitions and their
   # properties from one option to another. This property is useful for
@@ -556,8 +557,20 @@ rec {
   #
   mkAliasDefinitions = mkAliasAndWrapDefinitions id;
   mkAliasAndWrapDefinitions = wrap: option:
-    mkIf (isOption option && option.isDefined) (wrap (mkMerge option.definitions));
+    mkAliasIfDef option (wrap (mkMerge option.definitions));
 
+  # Similar to mkAliasAndWrapDefinitions but copies over the priority from the
+  # option as well.
+  #
+  # If a priority is not set, it assumes a priority of defaultPriority.
+  mkAliasAndWrapDefsWithPriority = wrap: option:
+    let
+      prio = option.highestPrio or defaultPriority;
+      defsWithPrio = map (mkOverride prio) option.definitions;
+    in mkAliasIfDef option (wrap (mkMerge defsWithPrio));
+
+  mkAliasIfDef = option:
+    mkIf (isOption option && option.isDefined);
 
   /* Compatibility. */
   fixMergeModules = modules: args: evalModules { inherit modules args; check = false; };
@@ -690,7 +703,16 @@ rec {
     use = id;
   };
 
-  doRename = { from, to, visible, warn, use }:
+  /* Like ‘mkAliasOptionModule’, but copy over the priority of the option as well. */
+  mkAliasOptionModuleWithPriority = from: to: doRename {
+    inherit from to;
+    visible = true;
+    warn = false;
+    use = id;
+    withPriority = true;
+  };
+
+  doRename = { from, to, visible, warn, use, withPriority ? false }:
     { config, options, ... }:
     let
       fromOpt = getAttrFromPath from options;
@@ -708,7 +730,9 @@ rec {
           warnings = optional (warn && fromOpt.isDefined)
             "The option `${showOption from}' defined in ${showFiles fromOpt.files} has been renamed to `${showOption to}'.";
         }
-        (mkAliasAndWrapDefinitions (setAttrByPath to) fromOpt)
+        (if withPriority
+          then mkAliasAndWrapDefsWithPriority (setAttrByPath to) fromOpt
+          else mkAliasAndWrapDefinitions (setAttrByPath to) fromOpt)
       ];
     };
 
diff --git a/lib/strings.nix b/lib/strings.nix
index 48420a367815..47c881cfbc7c 100644
--- a/lib/strings.nix
+++ b/lib/strings.nix
@@ -162,26 +162,6 @@ rec {
   */
   makeBinPath = makeSearchPathOutput "bin" "bin";
 
-
-  /* Construct a perl search path (such as $PERL5LIB)
-
-     Example:
-       pkgs = import <nixpkgs> { }
-       makePerlPath [ pkgs.perlPackages.libnet ]
-       => "/nix/store/n0m1fk9c960d8wlrs62sncnadygqqc6y-perl-Net-SMTP-1.25/lib/perl5/site_perl"
-  */
-  # FIXME(zimbatm): this should be moved in perl-specific code
-  makePerlPath = makeSearchPathOutput "lib" "lib/perl5/site_perl";
-
-  /* Construct a perl search path recursively including all dependencies (such as $PERL5LIB)
-
-     Example:
-       pkgs = import <nixpkgs> { }
-       makeFullPerlPath [ pkgs.perlPackages.CGI ]
-       => "/nix/store/fddivfrdc1xql02h9q500fpnqy12c74n-perl-CGI-4.38/lib/perl5/site_perl:/nix/store/8hsvdalmsxqkjg0c5ifigpf31vc4vsy2-perl-HTML-Parser-3.72/lib/perl5/site_perl:/nix/store/zhc7wh0xl8hz3y3f71nhlw1559iyvzld-perl-HTML-Tagset-3.20/lib/perl5/site_perl"
-  */
-  makeFullPerlPath = deps: makePerlPath (lib.misc.closePropagation deps);
-
   /* Depending on the boolean `cond', return either the given string
      or the empty string. Useful to concatenate against a bigger string.
 
diff --git a/lib/systems/default.nix b/lib/systems/default.nix
index 25df5e174069..9b25052ab88d 100644
--- a/lib/systems/default.nix
+++ b/lib/systems/default.nix
@@ -98,7 +98,7 @@ rec {
       in
         if final.parsed.kernel.name == pkgs.stdenv.hostPlatform.parsed.kernel.name &&
            (final.parsed.cpu.name == pkgs.stdenv.hostPlatform.parsed.cpu.name ||
-            (final.platform.isi686 && pkgs.stdenv.hostPlatform.isx86_64))
+            (final.isi686 && pkgs.stdenv.hostPlatform.isx86_64))
         then pkgs.runtimeShell
         else if final.isWindows
         then "${wine}/bin/${wine-name}"
diff --git a/lib/systems/examples.nix b/lib/systems/examples.nix
index 608db00a9683..ac1633a1a15f 100644
--- a/lib/systems/examples.nix
+++ b/lib/systems/examples.nix
@@ -47,7 +47,7 @@ rec {
   armv5te-android-prebuilt = rec {
     config = "armv5tel-unknown-linux-androideabi";
     sdkVer = "21";
-    ndkVer = "10e";
+    ndkVer = "18b";
     platform = platforms.armv5te-android;
     useAndroidPrebuilt = true;
   };
@@ -55,7 +55,7 @@ rec {
   armv7a-android-prebuilt = rec {
     config = "armv7a-unknown-linux-androideabi";
     sdkVer = "24";
-    ndkVer = "17c";
+    ndkVer = "18b";
     platform = platforms.armv7a-android;
     useAndroidPrebuilt = true;
   };
@@ -63,7 +63,7 @@ rec {
   aarch64-android-prebuilt = rec {
     config = "aarch64-unknown-linux-android";
     sdkVer = "24";
-    ndkVer = "17c";
+    ndkVer = "18b";
     platform = platforms.aarch64-multiplatform;
     useAndroidPrebuilt = true;
   };
diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix
index 7db09fc550e2..6947d41419e3 100644
--- a/lib/systems/parse.nix
+++ b/lib/systems/parse.nix
@@ -279,8 +279,14 @@ rec {
     "2" = # We only do 2-part hacks for things Nix already supports
       if elemAt l 1 == "cygwin"
         then { cpu = elemAt l 0;                      kernel = "windows";  abi = "cygnus";   }
+      # MSVC ought to be the default ABI so this case isn't needed. But then it
+      # becomes difficult to handle the gnu* variants for Aarch32 correctly for
+      # minGW. So it's easier to make gnu* the default for the MinGW, but
+      # hack-in MSVC for the non-MinGW case right here.
+      else if elemAt l 1 == "windows"
+        then { cpu = elemAt l 0;                      kernel = "windows";  abi = "msvc";     }
       else if (elemAt l 1) == "elf"
-      then { cpu = elemAt l 0; vendor = "unknown";    kernel = "none";     abi = elemAt l 1; }
+        then { cpu = elemAt l 0; vendor = "unknown";  kernel = "none";     abi = elemAt l 1; }
       else   { cpu = elemAt l 0;                      kernel = elemAt l 1;                   };
     "3" = # Awkwards hacks, beware!
       if elemAt l 1 == "apple"
@@ -288,7 +294,7 @@ rec {
       else if (elemAt l 1 == "linux") || (elemAt l 2 == "gnu")
         then { cpu = elemAt l 0;                      kernel = elemAt l 1; abi = elemAt l 2; }
       else if (elemAt l 2 == "mingw32") # autotools breaks on -gnu for window
-        then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "windows";  abi = "gnu"; }
+        then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "windows";                    }
       else if hasPrefix "netbsd" (elemAt l 2)
         then { cpu = elemAt l 0; vendor = elemAt l 1;    kernel = elemAt l 2;                }
       else if (elem (elemAt l 2) ["eabi" "eabihf" "elf"])
@@ -324,13 +330,12 @@ rec {
                else                                   getKernel args.kernel;
       abi =
         /**/ if args ? abi       then getAbi args.abi
-        else if isLinux   parsed then
+        else if isLinux parsed || isWindows parsed then
           if isAarch32 parsed then
             if lib.versionAtLeast (parsed.cpu.version or "0") "6"
             then abis.gnueabihf
             else abis.gnueabi
           else abis.gnu
-        else if isWindows parsed then abis.gnu
         else                     abis.unknown;
     };
 
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index 1604fbb39cbb..d8f412d3fc49 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -401,42 +401,4 @@ runTests {
     expected  = "«foo»";
   };
 
-
-# MISC
-
-  testOverridableDelayableArgsTest = {
-    expr =
-      let res1 = defaultOverridableDelayableArgs id {};
-          res2 = defaultOverridableDelayableArgs id { a = 7; };
-          res3 = let x = defaultOverridableDelayableArgs id { a = 7; };
-                 in (x.merge) { b = 10; };
-          res4 = let x = defaultOverridableDelayableArgs id { a = 7; };
-                in (x.merge) ( x: { b = 10; });
-          res5 = let x = defaultOverridableDelayableArgs id { a = 7; };
-                in (x.merge) ( x: { a = builtins.add x.a 3; });
-          res6 = let x = defaultOverridableDelayableArgs id { a = 7; mergeAttrBy = { a = builtins.add; }; };
-                     y = x.merge {};
-                in (y.merge) { a = 10; };
-
-          resRem7 = res6.replace (a: removeAttrs a ["a"]);
-
-          # fixed tests (delayed args): (when using them add some comments, please)
-          resFixed1 =
-                let x = defaultOverridableDelayableArgs id ( x: { a = 7; c = x.fixed.b; });
-                    y = x.merge (x: { name = "name-${builtins.toString x.fixed.c}"; });
-                in (y.merge) { b = 10; };
-          strip = attrs: removeAttrs attrs ["merge" "replace"];
-      in all id
-        [ ((strip res1) == { })
-          ((strip res2) == { a = 7; })
-          ((strip res3) == { a = 7; b = 10; })
-          ((strip res4) == { a = 7; b = 10; })
-          ((strip res5) == { a = 10; })
-          ((strip res6) == { a = 17; })
-          ((strip resRem7) == {})
-          ((strip resFixed1) == { a = 7; b = 10; c =10; name = "name-10"; })
-        ];
-    expected = true;
-  };
-
 }
diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh
index b83e1eb7d82d..a72777cbf2a6 100755
--- a/lib/tests/modules.sh
+++ b/lib/tests/modules.sh
@@ -149,6 +149,12 @@ checkConfigOutput "1 2 3 4 5 6 7 8 9 10" config.result ./loaOf-with-long-list.ni
 # Check loaOf with many merges of lists.
 checkConfigOutput "1 2 3 4 5 6 7 8 9 10" config.result ./loaOf-with-many-list-merges.nix
 
+# Check mkAliasOptionModuleWithPriority.
+checkConfigOutput "true" config.enable ./alias-with-priority.nix
+checkConfigOutput "true" config.enableAlias ./alias-with-priority.nix
+checkConfigOutput "false" config.enable ./alias-with-priority-can-override.nix
+checkConfigOutput "false" config.enableAlias ./alias-with-priority-can-override.nix
+
 cat <<EOF
 ====== module tests ======
 $pass Pass
diff --git a/lib/tests/modules/alias-with-priority-can-override.nix b/lib/tests/modules/alias-with-priority-can-override.nix
new file mode 100644
index 000000000000..a6b26895f3a8
--- /dev/null
+++ b/lib/tests/modules/alias-with-priority-can-override.nix
@@ -0,0 +1,52 @@
+# This is a test to show that mkAliasOptionModule sets the priority correctly
+# for aliased options.
+
+{ config, lib, ... }:
+
+with lib;
+
+{
+  options = {
+    # A simple boolean option that can be enabled or disabled.
+    enable = lib.mkOption {
+      type = types.nullOr types.bool;
+      default = null;
+      example = true;
+      description = ''
+        Some descriptive text
+      '';
+    };
+
+    # mkAliasOptionModule sets warnings, so this has to be defined.
+    warnings = mkOption {
+      internal = true;
+      default = [];
+      type = types.listOf types.str;
+      example = [ "The `foo' service is deprecated and will go away soon!" ];
+      description = ''
+        This option allows modules to show warnings to users during
+        the evaluation of the system configuration.
+      '';
+    };
+  };
+
+  imports = [
+    # Create an alias for the "enable" option.
+    (mkAliasOptionModuleWithPriority [ "enableAlias" ] [ "enable" ])
+
+    # Disable the aliased option, but with a default (low) priority so it
+    # should be able to be overridden by the next import.
+    ( { config, lib, ... }:
+      {
+        enableAlias = lib.mkForce false;
+      }
+    )
+
+    # Enable the normal (non-aliased) option.
+    ( { config, lib, ... }:
+      {
+        enable = true;
+      }
+    )
+  ];
+}
diff --git a/lib/tests/modules/alias-with-priority.nix b/lib/tests/modules/alias-with-priority.nix
new file mode 100644
index 000000000000..923483684cb1
--- /dev/null
+++ b/lib/tests/modules/alias-with-priority.nix
@@ -0,0 +1,52 @@
+# This is a test to show that mkAliasOptionModule sets the priority correctly
+# for aliased options.
+
+{ config, lib, ... }:
+
+with lib;
+
+{
+  options = {
+    # A simple boolean option that can be enabled or disabled.
+    enable = lib.mkOption {
+      type = types.nullOr types.bool;
+      default = null;
+      example = true;
+      description = ''
+        Some descriptive text
+      '';
+    };
+
+    # mkAliasOptionModule sets warnings, so this has to be defined.
+    warnings = mkOption {
+      internal = true;
+      default = [];
+      type = types.listOf types.str;
+      example = [ "The `foo' service is deprecated and will go away soon!" ];
+      description = ''
+        This option allows modules to show warnings to users during
+        the evaluation of the system configuration.
+      '';
+    };
+  };
+
+  imports = [
+    # Create an alias for the "enable" option.
+    (mkAliasOptionModuleWithPriority [ "enableAlias" ] [ "enable" ])
+
+    # Disable the aliased option, but with a default (low) priority so it
+    # should be able to be overridden by the next import.
+    ( { config, lib, ... }:
+      {
+        enableAlias = lib.mkDefault false;
+      }
+    )
+
+    # Enable the normal (non-aliased) option.
+    ( { config, lib, ... }:
+      {
+        enable = true;
+      }
+    )
+  ];
+}