distribution-nixpkgs 1.2 → 1.7.1.1
raw patch · 10 files changed
Files
- CHANGELOG.md +74/−0
- README.md +26/−0
- derivation-attr-paths.nix +42/−0
- distribution-nixpkgs.cabal +24/−12
- src/Distribution/Nixpkgs/License.hs +21/−20
- src/Distribution/Nixpkgs/Meta.hs +369/−40
- src/Distribution/Nixpkgs/PackageMap.hs +57/−23
- src/Language/Nix/PrettyPrinting.hs +27/−13
- test/data/all-system-tuples.json +1/−0
- test/hspec.hs +148/−1
+ 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++[](http://hackage.haskell.org/package/distribution-nixpkgs)+[](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