packages feed

distribution-nixpkgs 1.2 → 1.7.1.1

raw patch · 10 files changed

Files

+ CHANGELOG.md view
@@ -0,0 +1,74 @@+# Revision history for distribution-nixpkgs++## 1.7.1.1++* Adapt test suite to added representation of `RISCV64` and+  `LoongArch64` architectures in Cabal 3.12.++## 1.7.1++* GHC and nixpkgs now+  [use the system double `javascript-ghcjs`](https://github.com/NixOS/nixpkgs/commit/471b9cab41b218080f5e9f4abbc83eaaa60c6abf)+  instead of `js-ghcjs` to match Cabal's default rendering. With this release,+  `distribution-nixpkgs` does the same.+  Note that this means that this release needs to be used with nixpkgs unstable+  after [97d55ec](https://github.com/NixOS/nixpkgs/commit/97d55ec923b0cd3798a6a84e2e0a6b2c6b54f6a9)+  or nixpkgs stable 23.05 or newer.++## 1.7.0.1++* Adapt test suite to changed representation of some `Platform`s in Cabal 3.8.+* Update test data to include new nixpkgs architectures `rx`, `microblaze` and+  `microblazeel`.+* The distribution-nixpkgs repository has been merged into the+  [cabal2nix](https://github.com/NixOS/cabal2nix) repository.+  All URLs in the cabal file have been updated and the distribution-nixpkgs+  repository will be archived.++## 1.7.0++* `Distribution.Nixpkgs.Meta`+  * `pPrint (x :: Meta)` now renders every maintainer as a full attribute+    path instead of using `with`.+  * **API breaking change**: Changed types for all platform related fields /+    lenses of `Meta`, i.e. `platforms` and `hydraPlatforms`.+    * They are now wrapped in a `Maybe`. If `Nothing`, the respective attribute+      is not rendered.+    * Instead of `Platform` we now use `NixpkgsPlatform` which may also be a+      `NixpkgsPlatformGroup`, like `lib.platforms.linux`, in addition to the+      wrapped `Platform` in `NixpkgsPlatformSingle`.+  * **API breaking change**: Add new fields / lenses to `Meta`:+    * `badPlatforms`: Allows setting a list of unsupported platforms, works+      similarly to the `platform` / `hydraPlatform` lenses.+    * `mainProgram`: Allows setting the (base-)name of the main binary of a+      derivation. Not rendered if `Nothing`.+  * **API breaking change**: Remove `allKnownPlatforms`, its previous use can be+    replaced using `badPlatforms`.+  * Added `nixpkgsPlatformFromString` which parses a specific format used by+    hackage2nix's config files into either `NixpkgsPlatformSingle` or+    `NixpkgsPlatformGroup`.+* `Language.Nix.PrettyPrinting`: Added new helpers, `listattrDoc` and+  `toAscListSortedOn`.++## 1.6.2++* Expect `MonadFailDesugaring` (or equivalent behavior) to be the default,+  requiring GHC >= 8.6.1. Adds support for GHC 9.2.1 (rc1).++## 1.6.1++* `Distribution.Nixpkgs.Meta`: support `aarch64-darwin`+  * Render `Platform AArch64 OSX` to `"aarch64-darwin"`+  * Add `Platform AArch64 OSX` to `allKnownPlatforms`++## 1.6.0++* `Distribution.Nixpkgs.PackageMap`+  * `readNixpkgPackageMap`: instead of a list of arguments to pass to+    `nix-env`, take path to nixpkgs and an optional nix expression+    to pass to it as arguments.+  * `readNixpkgPackageMap`: populate `PackageMap` with *all* attribute+    paths that point to derivations instead of just one per derivation.+    This fixes `resolve` not finding certain identifiers if there were+    two attributes pointing to the same derivation in nixpkgs. See also+    [#9](https://github.com/NixOS/distribution-nixpkgs/issues/9).
+ README.md view
@@ -0,0 +1,26 @@+# distribution-nixpkgs++[![hackage release](https://img.shields.io/hackage/v/distribution-nixpkgs.svg?label=hackage)](http://hackage.haskell.org/package/distribution-nixpkgs)+[![stackage LTS package](http://stackage.org/package/distribution-nixpkgs/badge/lts)](http://stackage.org/lts/package/distribution-nixpkgs)++## Maintainer's Notes++### Keeping platform test cases up to date++As nixpkgs expands its list of supported platforms, new system tuples are added.+Therefore we need to adjust the test suite regularly in order to cover newly+added platforms. For this purpose, the test suite checks the platforms it verifies+against a list of system tuples generated from nixpkgs. This list needs to be+updated manually, so running the test suite doesn't depend on Nix being available.++To check if any new platforms need to be covered, do the following:++1. Run `./test/data/regenerate-all-system-tuples.sh /path/to/nixpkgs/checkout`.+   If no local nixpkgs is given, `<nixpkgs>` will be used.++2. Run the test suite: `cabal v2-test`.++3. If the test suite fails, add test cases for all missing system tuples.++4. In all cases, change the date of last update in+   `src/Distribution/Nixpkgs/Meta.hs` to the current day.
+ derivation-attr-paths.nix view
@@ -0,0 +1,42 @@+{ nixpkgsPath ? <nixpkgs>+, nixpkgsArgs ? {}+}@args:++let+  pkgs = import nixpkgsPath nixpkgsArgs;++  inherit (pkgs) lib;++  /* Condition for us to recurse:+     Either we are at the top-level or+     recurseForDerivations is true.++     Type :: list any -> any -> bool+  */+  recurseInto = path: x: path == [] ||+    (lib.isAttrs x && (x.recurseForDerivations or false));++  /* Takes the nixpkgs set and returns all attribute paths+     to reachable derivations within it as a list of lists of+     strings.++     Type :: attrs -> list (list string)+  */+  derivationPaths =+    let+      go = path: x:+        let+          inherit (builtins.tryEval x)+            value+            success+            ;+        in+          if !success then []+          else if lib.isDerivation value then [+            path+          ] else if recurseInto path value then lib.concatLists (+            lib.mapAttrsToList (n: go (path ++ [ n ])) value+          ) else [];+    in go [];+in+  derivationPaths pkgs
distribution-nixpkgs.cabal view
@@ -1,20 +1,26 @@ name:          distribution-nixpkgs-version:       1.2+version:       1.7.1.1 synopsis:      Types and functions to manipulate the Nixpkgs distribution description:   Types and functions to represent, query, and manipulate the Nixpkgs distribution. license:       BSD3 license-file:  LICENSE-maintainer:    Peter Simons <simons@cryp.to>-tested-with:   GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.3+author:        Peter Simons <simons@cryp.to>+maintainer:    sternenseemann <sternenseemann@systemli.org>+tested-with:   GHC == 8.10.7 || == 9.0.2 || == 9.2.8 || == 9.4.8 || == 9.6.6 || == 9.8.3 || == 9.10.1 category:      Distribution, Nix-homepage:      https://github.com/peti/distribution-nixpkgs#readme-bug-reports:   https://github.com/peti/distribution-nixpkgs/issues+homepage:      https://github.com/NixOS/cabal2nix/tree/master/distribution-nixpkgs#readme+bug-reports:   https://github.com/NixOS/cabal2nix/issues build-type:    Simple-cabal-version: >= 1.10+cabal-version: 1.18+data-files:    derivation-attr-paths.nix+extra-doc-files:    CHANGELOG.md+                    README.md+extra-source-files: test/data/all-system-tuples.json  source-repository head   type:     git-  location: https://github.com/peti/distribution-nixpkgs+  location: https://github.com/NixOS/cabal2nix+  subdir:   distribution-nixpkgs  library   exposed-modules:    Distribution.Nixpkgs.Hashes@@ -22,9 +28,10 @@                       Distribution.Nixpkgs.Meta                       Distribution.Nixpkgs.PackageMap                       Language.Nix.PrettyPrinting+  other-modules:      Paths_distribution_nixpkgs   hs-source-dirs:     src   build-depends:      base         > 4.2 && < 5-                    , Cabal        > 2.2+                    , Cabal        >= 2.4                     , aeson                     , bytestring                     , containers@@ -33,9 +40,7 @@                     , lens                     , pretty       >= 1.1.2                     , process-                    , split   default-language:   Haskell2010-  default-extensions: MonadFailDesugaring   other-extensions:   CPP                       TemplateHaskell                       RecordWildCards@@ -48,8 +53,15 @@   type:               exitcode-stdio-1.0   main-is:            hspec.hs   hs-source-dirs:     test-  build-depends:      base, deepseq, distribution-nixpkgs, hspec, lens+  build-depends:      base+                    , deepseq+                    , distribution-nixpkgs+                    , language-nix+                    , hspec+                    , lens+                    , Cabal+                    , aeson+                    , directory   default-language:   Haskell2010-  default-extensions: MonadFailDesugaring   ghc-options:        -Wall -Wcompat -Wincomplete-uni-patterns -Wincomplete-record-updates                       -Wredundant-constraints
src/Distribution/Nixpkgs/License.hs view
@@ -2,8 +2,8 @@  {- |    Known licenses in Nix expressions are represented using the-   attributes defined in @pkgs\/lib\/licenses.nix@, and unknown licenses-   are represented as a literal string.+   attributes defined in nixpkgs' @lib\/licenses.nix@, and+   unknown licenses are represented as a literal string.  -}  module Distribution.Nixpkgs.License ( License(..) ) where@@ -14,27 +14,28 @@ import Language.Nix.PrettyPrinting  -- | The representation for licenses used in Nix derivations. Known--- licenses are Nix expressions -- such as @stdenv.lib.licenses.bsd3@--- --, so their exact \"name\" is not generally known, because the path--- to @stdenv@ depends on the context defined in the expression. In--- Cabal expressions, for example, the BSD3 license would have to be--- referred to as @self.stdenv.lib.licenses.bsd3@. Other expressions,--- however, use different paths to the @licenses@ record. Because of tat+-- licenses are Nix expressions — such as @lib.licenses.bsd3@ —,+-- so their exact name is not generally known, because the path+-- to @lib@ depends on the context defined in the expression.+--+-- In Cabal expressions, for example, the BSD3 license would have to be+-- referred to as @self.lib.licenses.bsd3@. Other expressions,+-- however, use different paths to the @licenses@ record. Because of that -- situation, the library cannot provide an abstract data type that--- encompasses all known licenses. Instead, the @License@ type just--- distinguishes references to known and unknown licenses. The--- difference between the two is in the way they are pretty-printed:+-- encompasses all known licenses. ----- > > putStrLn (display (Known "stdenv.lib.license.gpl2"))--- > stdenv.lib.license.gpl2--- >--- > > putStrLn (display (Unknown (Just "GPL")))--- > "GPL"--- >--- > > putStrLn (display (Unknown Nothing))--- > "unknown"+-- Instead, the @License@ type just distinguishes references to known+-- and unknown licenses. The difference between the two is in the way+-- they are pretty-printed: ----- Note that the "Text" instance definition provides pretty-printing,+-- >>> putStrLn (prettyShow (Known "lib.license.gpl2"))+-- lib.license.gpl2+-- >>> putStrLn (prettyShow (Unknown (Just "GPL")))+-- "GPL"+-- >>> putStrLn (prettyShow (Unknown Nothing))+-- "unknown"+--+-- Note that the 'Pretty' instance definition provides pretty-printing, -- but no parsing as of now!  data License = Known String
src/Distribution/Nixpkgs/Meta.hs view
@@ -10,51 +10,265 @@  -}  module Distribution.Nixpkgs.Meta-  ( Meta, nullMeta-  , homepage, description, license, platforms, hydraPlatforms, maintainers, broken-  , allKnownPlatforms+  ( -- * Representation of the Nixpkgs Meta Set+    Meta, nullMeta+    -- ** Lenses for 'Meta'+  , homepage, description, license, platforms, badPlatforms, hydraPlatforms, mainProgram, maintainers, broken+    -- * Representation of Nixpkgs Platform Descriptions+  , NixpkgsPlatform (..)+  , nixpkgsPlatformFromString   ) where  -- Avoid name clash with Prelude.<> exported by post-SMP versions of base. #if MIN_VERSION_base(4,11,0) import Prelude hiding ( (<>) ) #endif+import Control.Applicative ( (<|>) ) import Control.DeepSeq-import Control.Lens+import Control.Lens hiding ( Strict )+import Data.List ( stripPrefix ) import Data.Set ( Set ) import qualified Data.Set as Set import Distribution.Nixpkgs.License+import qualified Distribution.Pretty as CabalPretty import Distribution.System import GHC.Generics ( Generic ) import Language.Nix.Identifier+import Language.Nix.Path ( path ) import Language.Nix.PrettyPrinting +-- | Representation of platform(s) as supported by nixpkgs:+--+--     * 'NixpkgsPlatformGroup' represents the name of a platform+--       list as found in @lib.platforms@. For example, at the+--       time of writing @NixpkgsPlatformGroup "darwin"@ would+--       represent the platform tuples @x86_64-darwin@, @aarch64-darwin@,+--       @i686-darwin@ and @armv7a-darwin@. Naturally, this is+--       subject to change as nixpkgs updates @lib.platforms@.+--     * 'NixpkgsPlatformSingle' indicates a single platform tuple+--       represented using Cabal's 'Platform'.+--+--   The former is useful to express related groups of+--   platforms which have similar properties. The latter+--   can be used to, for example, exclude a single, specific+--   platform.+--+--   @hackage2nix@ has used the latter approach historically+--   and is being extended to support nixpkgs' platform+--   groups as well for increased maintainer convenience.+--+--   The 'Pretty' instance allows for converting a 'NixpkgsPlatform'+--   into a Nix expression compatible with @meta.platforms@:+--+--   >>> pPrint $ NixpkgsPlatformSingle $ Platform X86_64 NetBSD+--   "x86_64-netbsd"+--+--   For 'NixpkgsPlatformGroup' we assume that the @lib@ attribute set is in+--   scope:+--+--   >>> pPrint $ NixpkgsPlatformGroup $ ident # "riscv"+--   lib.platforms.riscv+data NixpkgsPlatform+  = NixpkgsPlatformSingle Platform+  -- ^ Single platform represented as a Cabal platform. Can be understood as+  -- equivalent to Nix's system strings and will be converted to one usually.+  | NixpkgsPlatformGroup Identifier+  -- ^ 'Identifier' of the attribute name of a platform+  --   group in nixpkgs' @lib.platforms@.+  deriving (Show, Eq, Ord, Generic)++nixpkgsPlatformFromCabal :: Platform -> String+nixpkgsPlatformFromCabal (Platform arch os) = "\"" ++ nixArch ++ "-" ++ nixOs ++ "\""+  where nixArch =+          case arch of+            I386 -> "i686" -- rendered as i386 by default+            PPC -> "powerpc" -- rendered as ppc by default+            PPC64 -> "powerpc64" -- rendered as ppc64 by default+            _    -> CabalPretty.prettyShow arch+        nixOs =+          case os of+            OSX -> "darwin" -- rendered as osx by default+            _   -> CabalPretty.prettyShow os++-- | Obtain a 'NixpkgsPlatform' from a string representation intended for config+--   files.+--+--   * Every string starting with @lib.platforms.@ or @platforms.@ is+--     parsed into 'NixpkgsPlatformGroup'.+--   * All other strings are attempted to be interpreted as a nix(pkgs) style+--     system tuple and parsed into 'NixpkgsPlatformSingle'.+--+--   If none of these formats match the input 'String', 'Nothing' is returned.+--   A 'Just' result thus only indicates that the format of the platform is+--   sound — 'nixpkgsPlatformFromString' does /not/ check if the parsed platform+--   actually exists.+--+--   'NixpkgsPlatformSingle' is parsed from system tuples as understood by Nix+--   and nixpkgs. System tuples are derived from autoconf's+--   [target triplets](https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.70/autoconf.html#Manual-Configuration),+--   dropping the vendor part. They have the form @cpu-os@ where @os@ can either+--   be a single component or of the form @kernel-system@ (system is an autoconf+--   term here, not a Nix system). Note that three component systems are very+--   rare. The two main candidates @x86_64-linux-musl@ and @x86_64-linux-gnu@+--   are [prohibited for historical reasons](https://github.com/NixOS/nix/blob/ec07a70979a86cc436de7e46e03789b4606d25ab/configure.ac#L26-L28)+--   and represented as plain @x86_64-linux@ instead.+--+--   Note that 'nixpkgsPlatformFromString' expects to receive a /valid/ system+--   tuple, i.e. it will accept all system tuples that have a sound format+--   (with the caveat that it will accept n-tuples for @n >= 4@ even though+--   they are technically invalid). This is done because the ambiguity of+--   system tuples requires knowledge over its legal contents in order to check+--   their validity properly. Since @lib.systems.elaborate@ from nixpkgs is the+--   source of truth in this case, we want to avoid the need to continuously+--   update @distribution-nixpkgs@ to reflect its inner workings.+--+--   'nixpkgsPlatformFromString' does, however, some conversions to alleviate some+--   discrepancies between Cabal and nixpkgs. Parsing and rendering system tuples+--   using 'nixpkgsPlatformFromString' and rendering them via the 'Pretty'+--   instance of 'NixpkgsPlatform' should not change the system tuple+--   for tuples accepted by nixpkgs. This has been tested for all known tuples+--   (from @lib.platforms@ and @lib.systems.examples@) as of 2024-12-01.+--   Please open an issue if any newly added ones are not recognized properly.+--+--   __Warning__: 'nixpkgsPlatformFromString' consequently tries to preserve all+--   information of the passed system tuple. This means that it distinguishes+--   between things that Cabal wouldn't, e.g. `powerpc64` and `powerpc64le`. If+--   you use this function to obtain a 'Platform' that is later used to evaluate+--   a @.cabal@ file, it will behave unexpectedly in some situation. It is+--   recommended to use Cabal's own facilities or+--   @Distribution.Nixpkgs.Haskell.Platform@, provided by @cabal2nix@, instead.+--+--   'nixpkgsPlatformFromString' is also /not/ the inverse operation for+--   'NixpkgsPlatform'\'s 'Pretty' instance. It is not intended for parsing Nix+--   expressions.+--+--   >>> nixpkgsPlatformFromString "x86_64-netbsd"+--   Just (NixpkgsPlatformSingle (Platform X86_64 NetBSD))+--   >>> nixpkgsPlatformFromString "platforms.riscv"+--   Just (NixpkgsPlatformGroup (Identifier "riscv"))+--   >>> nixpkgsPlatformFromString "garbage"+--   Nothing+nixpkgsPlatformFromString :: String -> Maybe NixpkgsPlatform+nixpkgsPlatformFromString s = platformGroup <|> singlePlatform+  where platformGroup = do+          -- also accept "platform." as prefix to save some typing+          name <- stripPrefix "lib.platforms." s <|> stripPrefix "platforms." s+          Just $ NixpkgsPlatformGroup (ident # name)++        singlePlatform = NixpkgsPlatformSingle <$> cabalPlatformFromSystem s++-- | Parse a system tuple as understood by Nix and nixpkgs to a Cabal 'Platform'.+--   Used internally by 'nixpkgsPlatformFromString'.+--+--   >>> cabalPlatformFromSystem "x86_64-linux"+--   Just (Platform X86_64 Linux)+--   >>> cabalPlatformFromSystem "x86_64-linux-musl"+--   Just (Platform X86_64 (OtherOS "linux-musl"))+--   >>> cabalPlatformFromSystem "powerpc-darwin"+--   Just (Platform PPC OSX)+--   >>> cabalPlatformFromSystem "powerpc64le-linux"+--   Just (Platform (OtherArch "powerpc64le") Linux)+--   >>> cabalPlatformFromSystem "javascript-ghcjs"+--   Just (Platform JavaScript Ghcjs)+cabalPlatformFromSystem :: String -> Maybe Platform+cabalPlatformFromSystem s =+  case break (== '-') s of+    (arch, '-':os) ->+      if null arch || null os+      then Nothing+      else Just $ Platform (parseArch arch) (parseOS os)+    _ -> Nothing+  where -- Use permissive classification to also recognize autoconf / nixpkgs+        -- style OS strings, e.g. "darwin" where Cabal would expect "osx".+        --+        -- Note that we don't reimplement GHC_CONVERT_OS from GHC's configure+        -- file here at the moment. Our goal is to recognize all /well formed/+        -- nixpkgs system strings, nothing more. That this works correctly for+        -- nixpkgs systems currently in use is confirmed by the test suite.+        parseOS = classifyOS Permissive++        -- Use Strict for arch classification and add specific guards for cases+        -- where Cabal's naming expectations (which seems to be LLVM oriented)+        -- clash with what nixpkgs / autoconf use (e.g. Cabal uses "ppc" instead+        -- of "powerpc"). Using Permissive is not possible because Cabal is a bit+        -- overzealous in arch recognition: For example, it ignores endianess in+        -- the case of the POWER architectures, parsing "powerpcle" to "ppc" and+        -- "powerpc64le" to "ppc64" when they are clearly different platforms.+        --+        -- We also don't implement GHC_CONVERT_ARCH here, for the reasons stated+        -- above.+        parseArch as =+          case classifyArch Strict as of+            OtherArch "i686" -> I386+            OtherArch "powerpc" -> PPC+            OtherArch "powerpc64" -> PPC64+            a -> a++instance Pretty NixpkgsPlatform where+  pPrint (NixpkgsPlatformSingle p) = text $ nixpkgsPlatformFromCabal p+  pPrint (NixpkgsPlatformGroup p)  = pPrint+    $ path # [ ident # "lib", ident # "platforms", p ]++instance NFData NixpkgsPlatform+ -- | A representation of the @meta@ section used in Nix expressions. -- -- >>> :set -XOverloadedStrings -- >>> :{---   print (pPrint (Meta "http://example.org" "an example package" (Unknown Nothing)---                  (Set.singleton (Platform X86_64 Linux))---                  Set.empty---                  (Set.fromList ["joe","jane"])---                  True))+--   let meta = nullMeta+--         & homepage .~ "http://example.org"+--         & description .~ "An example package"+--         & license .~ Unknown Nothing+--         & platforms .~ Just (Set.singleton (NixpkgsPlatformSingle (Platform X86_64 Linux)))+--         & badPlatforms .~ Nothing+--         & hydraPlatforms .~ Just Set.empty+--         & mainProgram .~ Just "example-binary"+--         & maintainers .~ Set.fromList ["joe", "jane"]+--         & broken .~ True+--   in print $ pPrint meta -- :} -- homepage = "http://example.org";--- description = "an example package";+-- description = "An example package"; -- license = "unknown"; -- platforms = [ "x86_64-linux" ];--- hydraPlatforms = stdenv.lib.platforms.none;--- maintainers = with stdenv.lib.maintainers; [ jane joe ];+-- hydraPlatforms = lib.platforms.none;+-- mainProgram = "example-binary";+-- maintainers = [ lib.maintainers.jane lib.maintainers.joe ]; -- broken = true;- data Meta = Meta-  { _homepage       :: String           -- ^ URL of the package homepage-  , _description    :: String           -- ^ short description of the package-  , _license        :: License          -- ^ licensing terms-  , _platforms      :: Set Platform     -- ^ We re-use the Cabal type for convenience, but render it to conform to @pkgs\/lib\/platforms.nix@.-  , _hydraPlatforms :: Set Platform     -- ^ list of platforms built by Hydra (render to conform to @pkgs\/lib\/platforms.nix@)-  , _maintainers    :: Set Identifier   -- ^ list of maintainers from @pkgs\/lib\/maintainers.nix@-  , _broken         :: Bool             -- ^ set to @true@ if the build is known to fail+  { _homepage       :: String+  -- ^ URL of the package homepage+  , _description    :: String+  -- ^ short description of the package+  , _license        :: License+  -- ^ licensing terms+  , _platforms      :: Maybe (Set NixpkgsPlatform)+  -- ^ List of platforms that are supported by the package.+  --   'Nothing' prevents the attribute from being rendered.+  --   See 'NixpkgsPlatform' on the precise representation of platforms.+  , _badPlatforms   :: Maybe (Set NixpkgsPlatform)+  -- ^ List of platforms that are known to be unsupported. This is semantically+  --   equivalent to setting the following:+  --+  --   @+  --     platforms = lib.subtractLists+  --       (initialMeta.badPlatforms or []);+  --       (initialMeta.platforms or lib.platforms.all)+  --   @+  --+  --   'Nothing' prevents the attribute from being rendered.+  --   See 'NixpkgsPlatform' on the precise representation of platforms.+  , _hydraPlatforms :: Maybe (Set NixpkgsPlatform)+  -- ^ Platforms for which the package should be tested, built and added to the+  --   binary cache by Hydra. 'Nothing' prevents the attribute from being rendered.+  --  See 'NixpkgsPlatform' on the precise representation of platforms.+  , _mainProgram    :: Maybe String+  -- ^ Filename (as in basename) of the main executable provided by the described+  --   package. @Nothing@ if it is a library or no obvious default can be chosen.+  , _maintainers    :: Set Identifier+  -- ^ list of maintainers from @pkgs\/lib\/maintainers.nix@+  , _broken         :: Bool+  -- ^ set to @true@ if the build is known to fail   }   deriving (Show, Eq, Ord, Generic) @@ -67,38 +281,153 @@     [ onlyIf (not (null _homepage)) $ attr "homepage" $ string _homepage     , onlyIf (not (null _description)) $ attr "description" $ string _description     , attr "license" $ pPrint _license-    , onlyIf (_platforms /= allKnownPlatforms) $ renderPlatforms "platforms" _platforms-    , onlyIf (_hydraPlatforms /= _platforms) $ renderPlatforms "hydraPlatforms" _hydraPlatforms-    , setattr "maintainers" (text "with stdenv.lib.maintainers;") (Set.map (view ident) _maintainers)+    , maybe mempty (renderPlatforms "platforms") _platforms+    , maybe mempty (renderPlatforms "badPlatforms") _badPlatforms+    , maybe mempty (renderPlatforms "hydraPlatforms") _hydraPlatforms+    , maybe mempty (attr "mainProgram" . string) _mainProgram+    , listattrDoc "maintainers" mempty $ renderMaintainers _maintainers     , boolattr "broken" _broken _broken     ] -renderPlatforms :: String -> Set Platform -> Doc+-- | This function renders an Nix attribute binding suitable for use in+--   an attribute set representing the given set of 'NixpkgsPlatform's.+--+--   The @field@ argument is the name of the binding, usually either+--   @platforms@, @hydraPlatforms@ or @badPlatforms@.+--+--   Platforms are rendered in the following way:+--+--   * If the given 'Set' is empty, the binding's value is @lib.platforms.none@.+--     This has been preserved for “backwards compatibility” since changing this+--     would generate a huge diff for nixpkgs' @hackage-packages.nix@ file.+--+--   * First we render all 'NixpkgsPlatformSingle' values. This is done by+--     printing a Nix list containing Nix system strings. If there are no+--     platform groups, but the 'Set' is not empty, an empty list (@[ ]@) is+--     rendered.+--+--   * Finally we render all 'NixpkgsPlatformGroup's. Since these are lists, we+--     need to append them to the (cabal) platform list via the @++@ operator.+--     For each group we render @++ lib.platforms.<group name>@.+--+--   For example:+--+--   >>> :{+--     renderPlatforms "badPlatforms"+--       $ Set.fromList [+--         NixpkgsPlatformSingle (Platform (OtherArch "armv7l") Linux),+--         NixpkgsPlatformGroup (ident # "darwin"),+--         NixpkgsPlatformGroup (ident # "windows")+--       ]+--   :}+--   badPlatforms = [+--     "armv7l-linux"+--   ] ++ lib.platforms.darwin+--     ++ lib.platforms.windows;+--+--   >>> :{+--     renderPlatforms "platforms"+--       $ Set.fromList [+--         NixpkgsPlatformGroup (ident # "x86"),+--         NixpkgsPlatformGroup (ident # "riscv"),+--         NixpkgsPlatformGroup (ident # "freebsd")+--       ]+--   :}+--   platforms =+--        lib.platforms.freebsd+--     ++ lib.platforms.riscv+--     ++ lib.platforms.x86;+--+--   >>> :{+--     renderPlatforms "platforms"+--       $ Set.fromList [+--         NixpkgsPlatformGroup (ident # "x86")+--       ]+--   :}+--   platforms = lib.platforms.x86;+--+--   >>> :{+--     renderPlatforms "platforms"+--       $ Set.fromList [+--         NixpkgsPlatformSingle (Platform I386 Linux),+--         NixpkgsPlatformSingle (Platform X86_64 Linux),+--         NixpkgsPlatformSingle (Platform AArch64 Linux),+--         NixpkgsPlatformSingle (Platform X86_64 OSX),+--         NixpkgsPlatformSingle (Platform AArch64 OSX)+--       ]+--   :}+--   platforms = [+--     "i686-linux" "x86_64-linux" "x86_64-darwin" "aarch64-linux"+--     "aarch64-darwin"+--   ];+--+--   >>> :{+--     renderPlatforms "platforms"+--       $ Set.fromList [+--         NixpkgsPlatformSingle (Platform I386 Linux),+--         NixpkgsPlatformSingle (Platform X86_64 Linux),+--         NixpkgsPlatformSingle (Platform AArch64 Linux),+--         NixpkgsPlatformSingle (Platform X86_64 OSX),+--         NixpkgsPlatformSingle (Platform AArch64 OSX),+--         NixpkgsPlatformGroup (ident # "riscv"),+--         NixpkgsPlatformGroup (ident # "arm")+--       ]+--   :}+--   platforms = [+--     "i686-linux" "x86_64-linux" "x86_64-darwin" "aarch64-linux"+--     "aarch64-darwin"+--   ] ++ lib.platforms.arm+--     ++ lib.platforms.riscv;+renderPlatforms :: String -> Set NixpkgsPlatform -> Doc renderPlatforms field ps-  | Set.null ps = sep [ text field <+> equals <+> text "stdenv.lib.platforms.none" <> semi ]-  | otherwise   = sep [ text field <+> equals <+> lbrack-                      , nest 2 $ fsep $ map text (toAscList (Set.map fromCabalPlatform ps))-                      , rbrack <> semi-                      ]+  -- preserve old behavior: no platforms -> lib.platforms.none+  | Set.null ps = sep [ text field <+> equals <+> text "lib.platforms.none" <> semi ]+  | otherwise =+    sep [ text field <+> equals <+> unless (Set.null cabalPs) lbrack+        , unless (Set.null cabalPs) (nest 2 $ fsep renderedCabalPs)+        , unless (Set.null cabalPs) rbrack+        , unless (Set.null nixpkgsPs) (nest 2 renderedNixpkgsPs)+        ]+    <> semi+  where -- render nixpkgs platforms and cabal platform tuples separately+        -- since the former represents multiple platforms and meta doesn't+        -- support nested lists.+        (cabalPs, nixpkgsPs) = Set.partition isSinglePlatform ps+        isSinglePlatform (NixpkgsPlatformSingle _) = True+        isSinglePlatform _ = False +        renderedCabalPs = map pPrint $ Set.toAscList cabalPs++        -- append lib.platforms list via nix's ++ at the end+        -- if there is no cabal platforms list, don't emit leading +++        appendNixpkgsP acc elem = acc $$+          if isEmpty acc && Set.null cabalPs+          then nest 3 $ pPrint elem+          else text "++" <+> pPrint elem+        renderedNixpkgsPs = Set.foldl' appendNixpkgsP mempty nixpkgsPs++        -- Helper function, roughly the inverse of nixpkgs' optionals+        unless False x = x+        unless True _  = mempty++renderMaintainers :: Set Identifier -> [Doc]+renderMaintainers = map (pPrint . toPath) . toAscListSortedOn (view ident)+  where toPath m = path # [ ident # "lib", ident # "maintainers", m]++-- | 'Meta' record with no field set, i.e. evaluating any will throw:+--+--   >>> nullMeta ^. homepage+--   "*** Exception: undefined Meta.homepage+--   ... nullMeta :: Meta nullMeta = Meta   { _homepage = error "undefined Meta.homepage"   , _description = error "undefined Meta.description"   , _license = error "undefined Meta.license"   , _platforms = error "undefined Meta.platforms"+  , _badPlatforms = error "undefined Meta.badPlatforms"   , _hydraPlatforms = error "undefined Meta.hydraPlatforms"+  , _mainProgram = error "undefined Meta.mainProgram"   , _maintainers = error "undefined Meta.maintainers"   , _broken = error "undefined Meta.broken"   }--allKnownPlatforms :: Set Platform-allKnownPlatforms = Set.fromList [ Platform I386 Linux, Platform X86_64 Linux-                                 , Platform X86_64 OSX-                                 ]--fromCabalPlatform :: Platform -> String-fromCabalPlatform (Platform I386 Linux)   = "\"i686-linux\""-fromCabalPlatform (Platform X86_64 Linux) = "\"x86_64-linux\""-fromCabalPlatform (Platform X86_64 OSX)   = "\"x86_64-darwin\""-fromCabalPlatform p                       = error ("fromCabalPlatform: invalid Nix platform" ++ show p)
src/Distribution/Nixpkgs/PackageMap.hs view
@@ -1,3 +1,4 @@+-- | Build a lookup table from package identifiers to full attribute paths in nixpkgs. module Distribution.Nixpkgs.PackageMap   ( PackageMap, readNixpkgPackageMap   , resolve@@ -7,45 +8,78 @@ import qualified Data.Aeson as JSON import qualified Data.ByteString.Lazy as LBS import Data.Function-import Data.List as List-import Data.List.Split+import Data.List (minimumBy) import Data.Map.Strict ( Map ) import qualified Data.Map.Strict as Map import Data.Maybe import Data.Set ( Set ) import qualified Data.Set as Set import Language.Nix+import Paths_distribution_nixpkgs (getDataFileName) import System.Process  type PackageMap = Map Identifier (Set Path) -readNixpkgPackageMap :: [String] -> IO PackageMap-readNixpkgPackageMap = fmap identifierSet2PackageMap . readNixpkgSet+-- | Evaluate nixpkgs at a given (nix) path and build a 'Map'+--   keeping track of all 'Path's that end in a given 'Identifier'+--   and evaluate to a derivation.+--   This can be used to find an attribute 'Path' for an arbitrary+--   package name using 'resolve'.+--+--   Note: Evaluation of nixpkgs is very expensive (takes multiple+--   seconds), so cache the result of this function if possible.+--+--   >>> readNixpkgPackageMap "<nixpkgs>" (Just "{ config = { allowAliases = false; }; }")+--   fromList [ … ]+readNixpkgPackageMap :: String+                     -- ^ Path to nixpkgs, must be a valid nix path+                     --   (absolute, relative or @NIX_PATH@ lookup)+                     -> Maybe String+                     -- ^ (Optional) argument attribute set to pass to+                     --   nixpkgs. Must be a valid nix attribute set.+                     -> IO PackageMap+readNixpkgPackageMap nixpkgsPath nixpkgsArgs =+  identifierSet2PackageMap <$> readNixpkgSet nixpkgsPath nixpkgsArgs -readNixpkgSet :: [String] -> IO (Set String)-readNixpkgSet extraArgs = do-  (_, Just h, _, _) <- createProcess (proc "nix-env" (["-qaP", "--json"] ++ extraArgs))-                       { std_out = CreatePipe, env = Nothing }  -- TODO: ensure that overrides don't screw up our results+readNixpkgSet :: String -> Maybe String -> IO (Set [String])+readNixpkgSet nixpkgsPath nixpkgsArgs = do+  pathsExpr <- getDataFileName "derivation-attr-paths.nix"+  let nixInstantiate = proc "nix-instantiate"+        [ "--strict"+        , "--json"+        , "--eval"+        , pathsExpr+        , "--arg", "nixpkgsPath", nixpkgsPath+        , "--arg", "nixpkgsArgs", fromMaybe "{}" nixpkgsArgs+        ]+  (_, Just h, _, _) <- -- TODO: ensure that overrides don't screw up our results+    createProcess nixInstantiate { std_out = CreatePipe, env = Nothing }   buf <- LBS.hGetContents h-  let pkgmap :: Either String (Map String JSON.Object)-      pkgmap = JSON.eitherDecode buf-  either fail (return . Map.keysSet) pkgmap+  either fail return $ JSON.eitherDecode buf -identifierSet2PackageMap :: Set String -> PackageMap-identifierSet2PackageMap pkgset = foldr (uncurry insertIdentifier) Map.empty pkglist+identifierSet2PackageMap :: Set [String] -> PackageMap+identifierSet2PackageMap = foldr insertIdentifier Map.empty   where-    pkglist :: [(Identifier, Path)]-    pkglist = mapMaybe parsePackage (Set.toList pkgset)--    insertIdentifier :: Identifier -> Path -> PackageMap -> PackageMap-    insertIdentifier i = Map.insertWith Set.union i . Set.singleton+    insertIdentifier :: [String] -> (PackageMap -> PackageMap)+    insertIdentifier rawPath =+      case parsePackage rawPath of+        Nothing -> id+        Just (i, p) -> Map.insertWith Set.union i $ Set.singleton p -parsePackage :: String -> Maybe (Identifier, Path)-parsePackage x | null x                 = error "Distribution.Nixpkgs.PackageMap.parsepackage: empty string is no valid identifier"-               | xs <- splitOn "." x    = if needsQuoting (head xs)-                                             then Nothing-                                             else Just (ident # last xs, path # map (review ident) xs)+parsePackage :: [String] -> Maybe (Identifier, Path)+parsePackage x+  | null x = -- this case would be a bug in derivation-attr-paths.nix+      error "Distribution.Nixpkgs.PackageMap.parsepackage: empty path is no valid identifier"+  | otherwise =+      if any needsQuoting x+        then Nothing+        else Just (ident # last x, path # map (review ident) x) +-- | Finds the shortest 'Path' in a 'PackageMap' that has the+--   given 'Identifier' as its last component.+--+--   >>> resolve nixpkgs (ident # "pam")+--   Just (Bind (Identifier "pam") (Path [Identifier "pam"])) resolve :: PackageMap -> Identifier -> Maybe Binding resolve nixpkgs i = case Map.lookup i nixpkgs of                       Nothing -> Nothing
src/Language/Nix/PrettyPrinting.hs view
@@ -5,15 +5,15 @@  module Language.Nix.PrettyPrinting   ( onlyIf-  , setattr, toAscList-  , listattr+  , toAscList, toAscListSortedOn+  , setattr+  , listattr, listattrDoc   , boolattr   , attr   , string   , funargs   -- * Re-exports from other modules   , module Text.PrettyPrint.HughesPJClass-  , Text, disp   )   where @@ -23,10 +23,9 @@ #endif import Data.Char import Data.Function-import Data.List+import Data.List (sortBy) import Data.Set ( Set ) import qualified Data.Set as Set-import Distribution.Text ( Text, disp ) import "pretty" Text.PrettyPrint.HughesPJClass  attr :: String -> Doc -> Doc@@ -38,25 +37,40 @@ boolattr :: String -> Bool -> Bool -> Doc boolattr n p v = if p then attr n (bool v) else empty +listattrDoc :: String -> Doc -> [Doc] -> Doc+listattrDoc n prefix vs = onlyIf (not (null vs)) $+  sep [ text n <+> equals <+> prefix <+> lbrack,+        nest 2 $ fsep vs,+        rbrack <> semi+      ]+ listattr :: String -> Doc -> [String] -> Doc-listattr n prefix vs = onlyIf (not (null vs)) $-                sep [ text n <+> equals <+> prefix <+> lbrack,-                      nest 2 $ fsep $ map text vs,-                      rbrack <> semi-                    ]+listattr n p = listattrDoc n p . map text  setattr :: String -> Doc -> Set String -> Doc-setattr name prefix set = listattr name prefix (toAscList set)+setattr name prefix set = listattrDoc name prefix+  $ map text $ toAscList set +toAscListSortedOn :: (a -> String) -> Set a -> [a]+toAscListSortedOn f = sortBy (compare `on` map toLower . f) . Set.toList+ toAscList :: Set String -> [String]-toAscList = sortBy (compare `on` map toLower) . Set.toList+toAscList = toAscListSortedOn id  bool :: Bool -> Doc bool True  = text "true" bool False = text "false"  string :: String -> Doc-string = doubleQuotes . text+string = doubleQuotes . quoteString++quoteString :: String -> Doc+quoteString []          = mempty+quoteString ['\\']      = text "\\\\"+quoteString ('\\':x:xs)+  | x `elem` "\"rn$\\t" = text ['\\',x] <> quoteString xs+  | otherwise           = text "\\\\" <> quoteString (x:xs)+quoteString (x:xs)      = char x <> quoteString xs  prepunctuate :: Doc -> [Doc] -> [Doc] prepunctuate _ []     = []
+ test/data/all-system-tuples.json view
@@ -0,0 +1,1 @@+["aarch64-darwin","aarch64-freebsd","aarch64-genode","aarch64-linux","aarch64-netbsd","aarch64-none","aarch64-windows","aarch64_be-none","arm-none","armv5tel-linux","armv6l-linux","armv6l-netbsd","armv6l-none","armv7a-darwin","armv7a-linux","armv7a-netbsd","armv7l-linux","armv7l-netbsd","avr-none","i686-cygwin","i686-darwin","i686-freebsd","i686-genode","i686-linux","i686-netbsd","i686-none","i686-openbsd","i686-windows","javascript-ghcjs","loongarch64-linux","m68k-linux","m68k-netbsd","m68k-none","microblaze-linux","microblaze-none","microblazeel-linux","microblazeel-none","mips-linux","mips-none","mips64-linux","mips64-none","mips64el-linux","mipsel-linux","mipsel-netbsd","mmix-mmixware","msp430-none","or1k-none","powerpc-netbsd","powerpc-none","powerpc64-linux","powerpc64le-linux","powerpcle-none","riscv32-linux","riscv32-netbsd","riscv32-none","riscv64-linux","riscv64-netbsd","riscv64-none","rx-none","s390-linux","s390-none","s390x-linux","s390x-none","vc4-none","wasm32-none","wasm32-wasi","wasm64-wasi","x86_64-cygwin","x86_64-darwin","x86_64-freebsd","x86_64-genode","x86_64-linux","x86_64-netbsd","x86_64-none","x86_64-openbsd","x86_64-redox","x86_64-solaris","x86_64-windows"]
test/hspec.hs view
@@ -1,14 +1,23 @@+{-# LANGUAGE CPP #-} module Main ( main ) where  import Control.DeepSeq import Control.Exception import Control.Lens+import Control.Monad (forM_)+import Data.Aeson (decodeFileStrict)+import Data.Bifunctor (second)+import Data.Maybe (fromJust) import Distribution.Nixpkgs.License import Distribution.Nixpkgs.Meta+import Distribution.System (Platform (..), OS (..), Arch (..))+import Language.Nix.Identifier+import Language.Nix.PrettyPrinting+import System.Directory (doesFileExist) import Test.Hspec  main :: IO ()-main = hspec $+main = hspec $ do   describe "DeepSeq instances work properly for" $ do     it "License" $ mapM_ hitsBottom [Known undefined, Unknown (Just undefined)]     it "Meta" $ mapM_ hitsBottom@@ -19,6 +28,144 @@                   , nullMeta & maintainers .~ undefined                   , nullMeta & broken .~ undefined                   ]++  describe "Platform rendering and parsing:" $ do+    it "Checks cover all systems from all-system-tuples.json" $ do+      let allSystemTuplesJson = "test/data/all-system-tuples.json"+      available <- doesFileExist allSystemTuplesJson+      if not available+      then pendingWith $ "System tuple list not found at: " ++ allSystemTuplesJson+      else do+        allSystemTuples <- decodeFileStrict allSystemTuplesJson+        map fst nixpkgsSystemMapping `shouldMatchList` fromJust allSystemTuples++    forM_ platformMapping $ \(str, plat) -> describe str $ do+      it "is rendered correctly" $ checkRendering plat str+      it "is parsed correctly" $+        nixpkgsPlatformFromString str `shouldBe` Just plat++-- All system tuples from lib.platforms. Testing these allows us to+-- get notified about behavior change in Cabal as early as possible.+-- You can check if the list is up to date by running+-- regenerate-all-system-tuples.sh.+nixpkgsSystemMapping :: [(String, Platform)]+nixpkgsSystemMapping =+  [ -- lib.platforms.all+    ("aarch64-darwin", Platform AArch64 OSX)+  , ("aarch64-freebsd", Platform AArch64 FreeBSD)+  , ("aarch64-genode", Platform AArch64 (OtherOS "genode"))+  , ("aarch64-linux", Platform AArch64 Linux)+  , ("aarch64-netbsd", Platform AArch64 NetBSD)+  , ("aarch64-none", Platform AArch64 (OtherOS "none"))+  , ("aarch64-windows", Platform AArch64 Windows)+  , ("aarch64_be-none", Platform (OtherArch "aarch64_be") (OtherOS "none"))+  , ("arm-none", Platform Arm (OtherOS "none"))+  , ("armv5tel-linux", Platform (OtherArch "armv5tel") Linux)+  , ("armv6l-linux", Platform (OtherArch "armv6l") Linux)+  , ("armv6l-netbsd", Platform (OtherArch "armv6l") NetBSD)+  , ("armv6l-none", Platform (OtherArch "armv6l") (OtherOS "none"))+  , ("armv7a-darwin", Platform (OtherArch "armv7a") OSX)+  , ("armv7a-linux", Platform (OtherArch "armv7a") Linux)+  , ("armv7a-netbsd", Platform (OtherArch "armv7a") NetBSD)+  , ("armv7l-linux", Platform (OtherArch "armv7l") Linux)+  , ("armv7l-netbsd", Platform (OtherArch "armv7l") NetBSD)+  , ("avr-none", Platform (OtherArch "avr") (OtherOS "none"))+  , ("i686-cygwin", Platform I386 (OtherOS "cygwin"))+  , ("i686-darwin", Platform I386 OSX)+  , ("i686-freebsd", Platform I386 FreeBSD)+  , ("i686-genode", Platform I386 (OtherOS "genode"))+  , ("i686-linux", Platform I386 Linux)+  , ("i686-netbsd", Platform I386 NetBSD)+  , ("i686-none", Platform I386 (OtherOS "none"))+  , ("i686-openbsd", Platform I386 OpenBSD)+  , ("i686-windows", Platform I386 Windows)+  , ("javascript-ghcjs", Platform JavaScript Ghcjs)+#if MIN_VERSION_Cabal(3,12,0)+  , ("loongarch64-linux", Platform LoongArch64 Linux)+#else+  , ("loongarch64-linux", Platform (OtherArch "loongarch64") Linux)+#endif+  , ("m68k-linux", Platform M68k Linux)+  , ("m68k-netbsd", Platform M68k NetBSD)+  , ("m68k-none", Platform M68k (OtherOS "none"))+  , ("microblaze-linux", Platform (OtherArch "microblaze") Linux)+  , ("microblazeel-linux", Platform (OtherArch "microblazeel") Linux)+  , ("microblaze-none", Platform (OtherArch "microblaze") (OtherOS "none"))+  , ("microblazeel-none", Platform (OtherArch "microblazeel") (OtherOS "none"))+  , ("mips-linux", Platform Mips Linux)+  , ("mips-none", Platform Mips (OtherOS "none"))+  , ("mips64-linux", Platform (OtherArch "mips64") Linux)+  , ("mips64-none", Platform (OtherArch "mips64") (OtherOS "none"))+  , ("mips64el-linux", Platform (OtherArch "mips64el") Linux)+  , ("mipsel-linux", Platform (OtherArch "mipsel") Linux)+  , ("mipsel-netbsd", Platform (OtherArch "mipsel") NetBSD)+  , ("mmix-mmixware", Platform (OtherArch "mmix") (OtherOS "mmixware"))+  , ("msp430-none", Platform (OtherArch "msp430") (OtherOS "none"))+  , ("or1k-none", Platform (OtherArch "or1k") (OtherOS "none"))+  , ("powerpc-netbsd", Platform PPC NetBSD)+  , ("powerpc-none", Platform PPC (OtherOS "none"))+  , ("powerpc64-linux", Platform PPC64 Linux)+  , ("powerpc64le-linux", Platform (OtherArch "powerpc64le") Linux)+  , ("powerpcle-none", Platform (OtherArch "powerpcle") (OtherOS "none"))+  , ("riscv32-linux", Platform (OtherArch "riscv32") Linux)+  , ("riscv32-netbsd", Platform (OtherArch "riscv32") NetBSD)+  , ("riscv32-none", Platform (OtherArch "riscv32") (OtherOS "none"))+#if MIN_VERSION_Cabal(3,12,0)+  , ("riscv64-linux", Platform RISCV64 Linux)+  , ("riscv64-netbsd", Platform RISCV64 NetBSD)+  , ("riscv64-none", Platform RISCV64 (OtherOS "none"))+#else+  , ("riscv64-linux", Platform (OtherArch "riscv64") Linux)+  , ("riscv64-netbsd", Platform (OtherArch "riscv64") NetBSD)+  , ("riscv64-none", Platform (OtherArch "riscv64") (OtherOS "none"))+#endif+  , ("rx-none", Platform (OtherArch "rx") (OtherOS "none"))+  , ("s390-linux", Platform S390 Linux)+  , ("s390-none", Platform S390 (OtherOS "none"))+#if MIN_VERSION_Cabal(3,8,1)+  , ("s390x-linux", Platform S390X Linux)+  , ("s390x-none", Platform S390X (OtherOS "none"))+#else+  , ("s390x-linux", Platform (OtherArch "s390x") Linux)+  , ("s390x-none", Platform (OtherArch "s390x") (OtherOS "none"))+#endif+  , ("vc4-none", Platform (OtherArch "vc4") (OtherOS "none"))+#if MIN_VERSION_Cabal(3,8,1)+  , ("wasm32-none", Platform Wasm32 (OtherOS "none"))+  , ("wasm32-wasi", Platform Wasm32 Wasi)+  , ("wasm64-wasi", Platform (OtherArch "wasm64") Wasi)+#else+  , ("wasm32-none", Platform (OtherArch "wasm32") (OtherOS "none"))+  , ("wasm32-wasi", Platform (OtherArch "wasm32") (OtherOS "wasi"))+  , ("wasm64-wasi", Platform (OtherArch "wasm64") (OtherOS "wasi"))+#endif+  , ("x86_64-cygwin", Platform X86_64 (OtherOS "cygwin"))+  , ("x86_64-darwin", Platform X86_64 OSX)+  , ("x86_64-freebsd", Platform X86_64 FreeBSD)+  , ("x86_64-genode", Platform X86_64 (OtherOS "genode"))+  , ("x86_64-linux", Platform X86_64 Linux)+  , ("x86_64-netbsd", Platform X86_64 NetBSD)+  , ("x86_64-none", Platform X86_64 (OtherOS "none"))+  , ("x86_64-openbsd", Platform X86_64 OpenBSD)+  , ("x86_64-redox", Platform X86_64 (OtherOS "redox"))+  , ("x86_64-solaris", Platform X86_64 Solaris)+  , ("x86_64-windows", Platform X86_64 Windows)+  -- lib.systems.examples+  -- Currently no tuples are unique to the example list.+  ]++platformMapping :: [(String, NixpkgsPlatform)]+platformMapping = map (second NixpkgsPlatformSingle) nixpkgsSystemMapping+  ++ map platformGroupMapping [ "riscv", "x86", "linux", "darwin" ]++platformGroupMapping :: String -> (String, NixpkgsPlatform)+platformGroupMapping name =+  ("lib.platforms." ++ name, NixpkgsPlatformGroup (ident # name))++checkRendering :: NixpkgsPlatform -> String -> Expectation+checkRendering plat@(NixpkgsPlatformSingle _) str =+  prettyShow plat `shouldBe` "\"" ++ str ++ "\""+checkRendering plat str = prettyShow plat `shouldBe` str  hitsBottom :: NFData a => a -> Expectation hitsBottom x = evaluate (rnf x) `shouldThrow` anyErrorCall