packages feed

cpkg (empty) → 0.1.0.0

raw patch · 39 files changed

+6271/−0 lines, 39 filesdep +basedep +binarydep +bytestring

Dependencies added: base, binary, bytestring, bzlib, composition-prelude, containers, cpkg, dhall, directory, filemanip, filepath, hashable, hspec, hspec-megaparsec, http-client, http-client-tls, lzma, megaparsec, microlens, mtl, network-uri, optparse-applicative, prettyprinter, process, recursion, tar, temporary, text, zip-archive, zlib

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# cpkg++## 0.1.0.0++Initial release
+ LICENSE view
@@ -0,0 +1,11 @@+Copyright Vanessa McHale (c) 2018-2019++Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,264 @@+# cpkg++[![Build Status](https://travis-ci.org/vmchale/cpkg.svg?branch=master)](https://travis-ci.org/vmchale/cpkg)+[![Windows build status](https://ci.appveyor.com/api/projects/status/github/vmchale/cpkg?svg=true)](https://ci.appveyor.com/project/vmchale/cpkg)+[![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/cpkg/badge)](https://matrix.hackage.haskell.org/package/cpkg)+[![Hackage](https://img.shields.io/hackage/v/cpkg.svg)](http://hackage.haskell.org/package/cpkg)+[![Dependencies of latest version on Hackage](https://img.shields.io/hackage-deps/v/cpkg.svg)](https://hackage.haskell.org/package/cpkg)++`cpkg` is a build tool for C with a particular emphasis on cross compilation.+It is configured using+[Dhall](http://github.com/dhall-lang/dhall-haskell).++By considering a package to be a *function* taking a `cpkg`-supplied+installation directory to a series of steps, we can effectively package+C projects with diverse build systems and handle dependencies between them.++This tool provides reasonably good support for cross-compilation of C projects+and packages. It is not a full-fledged package manager.++- [Installation](#installation)+  - [Shell Completions](#shell-completions)+- [Example](#example)+  - [Configuration](#configuration)+  - [Dhall Prelude](#dhall-prelude)+  - [Cabal Integration](#cabal-integration)+- [Known Deficiencies](#known-deficiences)+  - [Security](#security)+  - [Contents](#contents)++## Installation++```+cabal new-install cpkg+```++### Shell Completions++Add the following to your `~/.bashrc` for shell completions:++```+eval "$(cpkg --bash-completion-script cpkg)"+```++### Packages++To view available packages, use `cpkg list`++```+vanessa@thinkpad ~/programming/haskell/done/cpkg 🌸 cpkg list++autoconf+    url: https://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.xz+    version: 2.69+    build dependencies: m4+++automake+    url: https://ftp.gnu.org/gnu/automake/automake-1.16.1.tar.xz+    version: 1.16.1+    build dependencies: autoconf+++at-spi2-atk+    url: http://ftp.gnome.org/pub/gnome/sources/at-spi2-atk/2.30/at-spi2-atk-2.30.0.tar.xz+    version: 2.30.0+    dependencies: at-spi2-core, atk, libxml2+    build dependencies: meson, ninja+++at-spi2-core+    url: http://ftp.gnome.org/pub/gnome/sources/at-spi2-core/2.30/at-spi2-core-2.30.0.tar.xz+    version: 2.30.0+    dependencies: libXtst, glib+    build dependencies: meson, ninja+++atk+    url: https://ftp.gnome.org/pub/gnome/sources/atk/2.30/atk-2.30.0.tar.xz+    version: 2.30.0+    build dependencies: gobject-introspection+⋮+```+++## Example++To install `tar`:++```+cpkg install tar+```++To install `emacs`:++```+cpkg install emacs+```++### Configuration++Here is the configuration for Lua:++```dhall+let prelude = https://raw.githubusercontent.com/vmchale/cpkg/master/dhall/cpkg-prelude.dhall+in++let lua =+  λ(v : List Natural) →+    let printLuaOS =+      λ(os : types.OS) →+        merge+          { FreeBSD   = λ(_ : {}) → "freebsd"+          , OpenBSD   = λ(_ : {}) → "bsd"+          , NetBSD    = λ(_ : {}) → "bsd"+          , Solaris   = λ(_ : {}) → "solaris"+          , Dragonfly = λ(_ : {}) → "bsd"+          , Linux     = λ(_ : {}) → "linux"+          , Darwin    = λ(_ : {}) → "macosx"+          , Windows   = λ(_ : {}) → "mingw"+          , Redox     = λ(_ : {}) → "generic"+          , Haiku     = λ(_ : {}) → "generic"+          , IOS       = λ(_ : {}) → "generic"+          , AIX       = λ(_ : {}) → "generic"+          , Hurd      = λ(_ : {}) → "generic"+          , Android   = λ(_ : {}) → "generic"+          , NoOs      = λ(_ : {}) → "c89"+          }+          os+    in++    let luaBuild =+      λ(cfg : types.BuildVars) →+        let cc = prelude.mkCCArg cfg+        in++        let ldflags =+          (prelude.mkLDFlags cfg.linkDirs).value+        in++        let cflags =+          (prelude.mkCFlags cfg.includeDirs).value+        in++        let os =+          prelude.osCfg cfg+        in++        [ prelude.call (prelude.defaultCall ⫽ { program = "make"+                                              , arguments = cc # [ printLuaOS os, "MYLDFLAGS=${ldflags}", "MYCFLAGS=${cflags}", "MYLIBS=-lncurses" ]+                                              })+        ]+    in++    let luaInstall =+      λ(cfg : types.BuildVars) →+        [ prelude.call (prelude.defaultCall ⫽ { program = "make"+                                              , arguments = [ "install", "INSTALL_TOP=${cfg.installDir}" ]+                                              }) ]+          # prelude.symlinkBinaries [ "bin/lua", "bin/luac" ]+    in++    prelude.simplePackage { name = "lua", version = v } ⫽+      { pkgUrl = "http://www.lua.org/ftp/lua-${prelude.showVersion v}.tar.gz"+      , configureCommand = prelude.doNothing+      , buildCommand = luaBuild+      , installCommand = luaInstall+      , pkgDeps = [ prelude.unbounded "readline"+                  , prelude.unbounded "ncurses"+                  ]+      }+in++lua [5,3,5]+```++### Cabal Integration++After running++```+cpkg install libX11 --target=arm-linux-gnueabihf+cpkg install libXext --target=arm-linux-gnueabihf+cpkg install libXrandr --target=arm-linux-gnueabihf+cpkg install libXinerama --target=arm-linux-gnueabihf+cpkg install libXScrnSaver --target=arm-linux-gnueabihf+```++You can dump flags to be passed to cabal with++```+cpkg dump-cabal libX11 libXext libXrandr libXinerama libXScrnSaver --target=arm-linux-gnueabihf+```++which will produce something like++```+--extra-lib-dirs=/home/vanessa/.cpkg/arm-linux-gnueabihf/libX11-1.6.7-820c8166b4caadb/lib --extra-lib-dirs=/home/vanessa/.cpkg/arm-linux-gnueabihf/libXext-1.3.3-1bad0a89c6794a53/lib --extra-lib-dirs=/home/vanessa/.cpkg/arm-linux-gnueabihf/libXrandr-1.5.1-f58f951a622e5c2/lib --extra-lib-dirs=/home/vanessa/.cpkg/arm-linux-gnueabihf/libXinerama-1.1.4-516496f7e04d34be/lib --extra-lib-dirs=/home/vanessa/.cpkg/arm-linux-gnueabihf/libXScrnSaver-1.2.3-60f6993b79a87725/lib+```++This could be used, for example, to cross-compile `xmonad`, viz.++```+cabal new-install xmonad --with-ghc arm-linux-gnueabihf-ghc --with-ghc-pkg arm-linux-gnueabihf-ghc-pkg $(cpkg dump-cabal libX11 libXext libXrandr libXinerama libXScrnSaver --target=arm-linux-gnueabihf)+```++### Dhall Prelude++There is+a [prelude](https://github.com/vmchale/cpkg/blob/master/dhall/cpkg-prelude.dhall)+available containing functions which simplify the process of writing package+descriptions. As an example, we can install `sed`++```dhall+let prelude = https://raw.githubusercontent.com/vmchale/cpkg/master/dhall/cpkg-prelude.dhall+in++let sed =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "sed", version = v }+in++sed [4,5]+```++## Known Deficiencies++### Security++This tool is insecure.++### Performance++This tool is not performant.++### Dependency Solver++Currently, there is no dependency solver. It should be relatively easy to add+a version-based dependency solver to the code.++### Garbage Collection++Currently, there is no garbage collector à la `$ nix-collect-garbage`. This will+*not* be relatively easy to add, because it will require that the global package+index be re-implemented (ideally using a proper database).++## Contents++Lovingly provided by [polyglot](https://github.com/vmchale/polyglot):++```+-------------------------------------------------------------------------------+ Language             Files       Lines         Code     Comments       Blanks+-------------------------------------------------------------------------------+ Bash                     5          49           43            3            3+ Cabal                    1         153          139            0           14+ Cabal Project            1           2            2            0            0+ Dhall                    3        4147         3725            0          422+ Haskell                 31        1687         1377           28          282+ Markdown                 6         469          401            0           68+ YAML                     4         156          141            0           15+-------------------------------------------------------------------------------+ Total                   51        6663         5828           31          804+-------------------------------------------------------------------------------+```
+ app/Main.hs view
@@ -0,0 +1,165 @@+module Main (main) where++import           Control.Monad       (void, when)+import           Data.Semigroup+import qualified Data.Text           as T+import qualified Data.Version        as V+import           Options.Applicative hiding (auto)+import           Package.C           hiding (Command)+import qualified Paths_cpkg          as P+import           System.Directory    (doesDirectoryExist, removeDirectoryRecursive)++cpkgVersion :: V.Version+cpkgVersion = P.version++data DumpTarget = Linker { _pkgGet :: String }+                | Compiler { _pkgGet :: String }+                | PkgConfig { _pkgGet :: String }+                | IncludePath { _pkgGet :: String }+                | LibPath { _pkgGet :: String }++data Command = Install { _pkgName :: String, _verbosity :: Verbosity, _target :: Maybe Platform, _static :: Bool, _packageSet :: Maybe String }+             | Check { _dhallFile :: String, _verbosity :: Verbosity }+             | CheckSet { _dhallFile :: String, _verbosity :: Verbosity }+             | Dump { _dumpTarget :: DumpTarget, _host :: Maybe Platform }+             | DumpCabal { _pkgGets :: [String], _host :: Maybe Platform }+             | List { _packageSet :: Maybe String }+             | Nuke++verbosityInt :: Parser Int+verbosityInt = length <$>+    many (flag' () (short 'v' <> long "verbose" <> help "Turn up verbosity"))++verbosity :: Parser Verbosity+verbosity = fmap intToVerbosity verbosityInt++intToVerbosity :: Int -> Verbosity+intToVerbosity 0 = Normal+intToVerbosity 1 = Verbose+intToVerbosity 2 = Loud+intToVerbosity 3 = Diagnostic+intToVerbosity _ = Normal++wrapper :: ParserInfo Command+wrapper = info (helper <*> versionInfo <*> userCmd)+    (fullDesc+    <> progDesc "The cpkg build tool and package manager."+    <> header "cpkg - a build tool for C")++versionInfo :: Parser (a -> a)+versionInfo = infoOption ("cpkg version: " ++ V.showVersion cpkgVersion) (short 'V' <> long "version" <> help "Show version")++dumpTarget :: Parser DumpTarget+dumpTarget = hsubparser+    (command "linker" (info (Linker <$> package) (progDesc "Dump linker flags for a package"))+    <> command "compiler" (info (Compiler <$> package) (progDesc "Dump compiler flags for a package"))+    <> command "pkg-config" (info (PkgConfig <$> package) (progDesc "Dump pkg-config path for a package")) -- TODO: make pkg-config recursive or something?+    <> command "include" (info (IncludePath <$> package) (progDesc "Dump C_INCLUDE_PATH for a package"))+    <> command "library" (info (LibPath <$> package) (progDesc "Dump LD_LIBRARY_PATH or LIBRARY_PATH for a package"))+    )++userCmd :: Parser Command+userCmd = hsubparser+    (command "install" (info install (progDesc "Install a package from the global package set"))+    <> command "check" (info check (progDesc "Check a Dhall expression to ensure it can be used to build a package"))+    <> command "check-set" (info checkSet (progDesc "Check a package set defined in Dhall"))+    <> command "dump" (info dump (progDesc "Display flags to link against a particular library"))+    <> command "dump-cabal" (info dumpCabal (progDesc "Display flags to use with cabal new-build"))+    <> command "list" (info list (progDesc "List all available packages"))+    <> command "nuke" (info (pure Nuke) (progDesc "Remove all globally installed libraries"))+    )++list :: Parser Command+list = List <$> packageSet++ftypeCompletions :: String -> Mod ArgumentFields a+ftypeCompletions ext = completer . bashCompleter $ "file -X '!*." ++ ext ++ "' -o plusdirs"++dhallCompletions :: Mod ArgumentFields a+dhallCompletions = ftypeCompletions "dhall"++install :: Parser Command+install = Install+    <$> argument str+        (metavar "PACKAGE"+        <> help "Name of package to install")+    <*> verbosity+    <*> target+    <*> static'+    <*> packageSet++packageSet :: Parser (Maybe String)+packageSet = optional+    (strOption+    (metavar "EXPRESSION"+    <> long "pkg-set"+    <> help "Dhall expression for the package set to be used"+    ))++static' :: Parser Bool+static' =+    switch+    (long "static"+    <> help "Build static libaries")++check :: Parser Command+check = Check <$> dhallFile <*> verbosity++checkSet :: Parser Command+checkSet = CheckSet <$> dhallFile <*> verbosity++target :: Parser (Maybe Platform)+target = optional+    (strOption+    (metavar "TARGET"+    <> long "target"+    <> help "Host platform, e.g. arm-linux-gnueabihf"+    ))++package :: Parser String+package =+    argument str+    (metavar "PACKAGE"+    <> help "Name of package you want to link against"+    <> completer (listIOCompleter allPackages)+    )++dumpCabal :: Parser Command+dumpCabal = DumpCabal+    <$> some package+    <*> target++dump :: Parser Command+dump = Dump+    <$> dumpTarget+    <*> target++dhallFile :: Parser String+dhallFile =+    argument str+    (metavar "EXPRESSION"+    <> help "File containing a Dhall expression"+    <> dhallCompletions+    )++run :: Command -> IO ()+run (Install pkId v host' sta pkSet) = do+    parsedHost <- parseHostIO host'+    runPkgM v $ buildByName (T.pack pkId) parsedHost pkSet sta+run (Check file' v) = void $ getCPkg v file'+run (CheckSet file' v) = void $ getPkgs v file'+run (Dump (Linker name) host) = runPkgM Normal $ printLinkerFlags name host+run (Dump (Compiler name) host) = runPkgM Normal $ printCompilerFlags name host+run (Dump (PkgConfig name) host) = runPkgM Normal $ printPkgConfigPath name host+run (Dump (IncludePath name) host) = runPkgM Normal $ printIncludePath name host+run (Dump (LibPath name) host) = runPkgM Normal $ printLibPath name host+run (DumpCabal names host) = runPkgM Normal $ printCabalFlags names host+run Nuke = do+    pkgDir <- globalPkgDir+    exists <- doesDirectoryExist pkgDir+    when exists $+        removeDirectoryRecursive pkgDir+run (List pkSet) = displayPackageSet pkSet++main :: IO ()+main = run =<< execParser wrapper
+ cabal.project view
@@ -0,0 +1,2 @@+packages: ./+constraints: cpkg +development
+ cpkg.cabal view
@@ -0,0 +1,153 @@+cabal-version: 1.18+name: cpkg+version: 0.1.0.0+license: BSD3+license-file: LICENSE+copyright: Copyright: (c) 2018-2019 Vanessa McHale+maintainer: vanessa.mchale@iohk.io+author: Vanessa McHale+synopsis: Build tool for C+description:+    A build tool and package manager configured using [Dhall](https://github.com/dhall-lang/dhall-haskell).+category: Packaging, Package Management, Dhall, C+build-type: Simple+extra-source-files:+    cabal.project+    dhall/cpkg-prelude.dhall+    dhall/cpkg-types.dhall+    pkgs/pkg-set.dhall+extra-doc-files: README.md+                 CHANGELOG.md++source-repository head+    type: git+    location: https://github.com/vmchale/cpkg++flag development+    description:+        Enable `-Werror`+    default: False+    manual: True++library+    exposed-modules:+        Package.C+    build-tools: cpphs -any+    hs-source-dirs: src+    other-modules:+        Package.C.Dhall+        Package.C.Dhall.Type+        Package.C.Type+        Package.C.Type.Shared+        Package.C.Type.Tree+        Package.C.Type.Verbosity+        Package.C.Type.Version+        Package.C.Type.Vars+        Package.C.Triple+        Package.C.Triple.Type+        Package.C.Triple.Parse+        Package.C.Build+        Package.C.Build.OS+        Package.C.Build.Tree+        Package.C.Unpack+        Package.C.Error+        Package.C.Fetch+        Package.C.Monad+        Package.C.Db.Type+        Package.C.Db.Register+        Package.C.Db.Monad+        Package.C.Db.Memory+        Package.C.PackageSet+        Package.C.Logging+        System.Process.Ext+        System.Directory.Executable+        Data.Text.Prettyprint.Doc.Custom+        CPkgPrelude+    default-language: Haskell2010+    other-extensions: DeriveGeneric DeriveAnyClass OverloadedStrings+                      DerivingStrategies GeneralizedNewtypeDeriving RankNTypes+    ghc-options: -Wall+    build-depends:+        base >=4.3 && <5,+        containers >=0.6.0.0,+        dhall >=1.19.0,+        text -any,+        temporary -any,+        bytestring -any,+        zlib -any,+        bzlib -any,+        lzma -any,+        tar -any,+        zip-archive -any,+        prettyprinter -any,+        http-client -any,+        http-client-tls -any,+        directory >=1.3.1.0,+        filepath -any,+        process -any,+        mtl -any,+        hashable -any,+        binary -any,+        microlens -any,+        composition-prelude -any,+        recursion >=2.0.0.0,+        filemanip -any,+        network-uri -any,+        megaparsec -any++    if (flag(development) && impl(ghc <=8.2))+        ghc-options: -Werror++    if impl(ghc >=8.0)+        ghc-options: -Wincomplete-uni-patterns -Wincomplete-record-updates+                     -Wredundant-constraints -Widentities++    if impl(ghc >=8.4)+        ghc-options: -Wmissing-export-lists++executable cpkg+    main-is: Main.hs+    hs-source-dirs: app+    other-modules:+        Paths_cpkg+    default-language: Haskell2010+    ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall+    build-depends:+        base -any,+        cpkg -any,+        optparse-applicative -any,+        directory -any,+        text -any++    if (flag(development) && impl(ghc <=8.2))+        ghc-options: -Werror++    if impl(ghc >=8.0)+        ghc-options: -Wincomplete-uni-patterns -Wincomplete-record-updates+                     -Wredundant-constraints -Widentities++    if impl(ghc >=8.4)+        ghc-options: -Wmissing-export-lists++test-suite cpkg-test+    type: exitcode-stdio-1.0+    main-is: Spec.hs+    hs-source-dirs: test+    default-language: Haskell2010+    ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall+    build-depends:+        base -any,+        cpkg -any,+        hspec -any,+        hspec-megaparsec -any,+        megaparsec -any++    if flag(development)+        ghc-options: -Werror++    if impl(ghc >=8.0)+        ghc-options: -Wincomplete-uni-patterns -Wincomplete-record-updates+                     -Wredundant-constraints -Widentities++    if impl(ghc >=8.4)+        ghc-options: -Wmissing-export-lists
+ dhall/cpkg-prelude.dhall view
@@ -0,0 +1,1154 @@+{- Dhall prelude imports -}+let concatMapSep = https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/Prelude/Text/concatMapSep+in++let concatMapText = https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/Prelude/Text/concatMap+in++let concatMap = https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/Prelude/List/concatMap+in++let map = https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/Prelude/List/map+in++let mapOptional = https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/Prelude/Optional/map+in++{- Imported types -}+let types = ../dhall/cpkg-types.dhall+in++let showVersion =+  concatMapSep "." Natural Natural/show+in++let maybeAppend =+  λ(a : Type) →+  λ(x : Optional a) →+  λ(xs : List a) →+    Optional/fold a x (List a) (λ(x : a) → (xs # [x])) xs+in++{- Print the architecture for use with GCC -}+let printArch =+  λ(arch : types.Arch) →+    merge+      { X64         = λ(_ : {}) → "x86_64"+      , AArch       = λ(_ : {}) → "aarch64"+      , Arm         = λ(_ : {}) → "arm"+      , RISCV64     = λ(_ : {}) → "riscv64"+      , PowerPC     = λ(_ : {}) → "powerpc"+      , PowerPC64   = λ(_ : {}) → "powerpc64"+      , PowerPC64le = λ(_ : {}) → "powerpc64le"+      , Sparc64     = λ(_ : {}) → "sparc64"+      , S390x       = λ(_ : {}) → "s390x"+      , Alpha       = λ(_ : {}) → "alpha"+      , M68k        = λ(_ : {}) → "m68k"+      , Mips        = λ(_ : {}) → "mips"+      , MipsEl      = λ(_ : {}) → "mipsel"+      , Mips64      = λ(_ : {}) → "mips64"+      , Mips64El    = λ(_ : {}) → "mips64el"+      , X86         = λ(_ : {}) → "i686"+      , SH4         = λ(_ : {}) → "sh4"+      , HPPA        = λ(_ : {}) → "hppa"+      , HPPA64      = λ(_ : {}) → "hppa64"+      }+      arch+in++let printManufacturer =+  λ(x : types.Manufacturer) →+    merge+      { Unknown = λ(_ : {}) → "unknown"+      , Apple   = λ(_ : {}) → "apple"+      , IBM     = λ(_ : {}) → "ibm"+      , PC      = λ(_ : {}) → "pc"+      }+      x+in++let printOS =+  λ(os : types.OS) →+    merge+      { FreeBSD   = λ(_ : {}) → "freebsd"+      , OpenBSD   = λ(_ : {}) → "openbsd"+      , NetBSD    = λ(_ : {}) → "netbsd"+      , Solaris   = λ(_ : {}) → "solaris"+      , Dragonfly = λ(_ : {}) → "dragonfly"+      , Linux     = λ(_ : {}) → "linux"+      , Darwin    = λ(_ : {}) → "darwin"+      , Windows   = λ(_ : {}) → "w64"+      , Redox     = λ(_ : {}) → "redox"+      , Haiku     = λ(_ : {}) → "haiku"+      , IOS       = λ(_ : {}) → "darwin"+      , AIX       = λ(_ : {}) → "aix"+      , Hurd      = λ(_ : {}) → "hurd"+      , Android   = λ(_ : {}) → "android"+      , NoOs      = λ(_ : {}) → "none"+      }+      os+in++{- Print the ABI for use with GCC -}+let printABI =+  λ(os : types.ABI) →+    merge+      { GNU       = λ(_ : {}) → "gnu"+      , GNUabi64  = λ(_ : {}) → "gnuabi64"+      , GNUeabi   = λ(_ : {}) → "gnueabi"+      , GNUeabihf = λ(_ : {}) → "gnueabihf"+      , GNUspe    = λ(_ : {}) → "gnuspe"+      , MinGw     = λ(_ : {}) → "mingw32"+      }+      os+in++{- Print target triple for use with GCC -}+let printTargetTriple =+  λ(t : types.TargetTriple) →+    "${printArch t.arch}-${printOS t.os}" ++ Optional/fold types.ABI t.abi Text (λ(abi : types.ABI) → "-${printABI abi}") ""+in++{- Print --host flag for use with ./configure scripts -}+let mkHost =+  mapOptional types.TargetTriple Text (λ(tgt : types.TargetTriple) → "--host=${printTargetTriple tgt}")+in++{- Pick executable for 'make'. Use 'gmake' on BSDs, 'make' everywhere else. -}+let makeExe =+  λ(os : types.OS) →++    let gmake = λ(_ : {}) → "gmake"+    in+    let make  = λ(_ : {}) → "make"+    in++    merge+      { FreeBSD   = gmake+      , OpenBSD   = gmake+      , NetBSD    = gmake+      , Solaris   = gmake+      , Dragonfly = gmake+      , Linux     = make+      , Darwin    = make+      , Windows   = make+      , Redox     = make+      , Haiku     = make+      , IOS       = make+      , AIX       = make+      , Hurd      = make+      , Android   = make+      , NoOs      = make -- this is bad but it's meaningless in this context+      }+      os+in++let mkExe =+  λ(x : Text) →+    types.Command.MakeExecutable { file = x }+in++let mkExes =+  map Text types.Command mkExe+in++let writeFile =+  types.Command.Write+in++let defaultEnv =+  None (List types.EnvVar)+in++let defaultCall =+  { arguments = [] : List Text+  , environment = defaultEnv+  , procDir = None Text+  }+in++let call =+  types.Command.Call+in++let symlinkBinary =+  λ(file : Text) →+    types.Command.SymlinkBinary { file = file }+in++let symlink =+  λ(tgt : Text) →+  λ(lnk : Text) →+    types.Command.Symlink { tgt = tgt, linkName = lnk }+in++let copyFile =+  λ(src : Text) →+  λ(dest : Text) →+    types.Command.CopyFile { src = src, dest = dest }+in++let symlinkBinaries =+  map Text types.Command symlinkBinary+in++{- This is to be used on the build OS -}+let isUnix =+  λ(os : types.OS) →++    let true = λ(_ : {}) → True+    in+    let false = λ(_ : {}) → False+    in++    merge+      { FreeBSD   = true+      , OpenBSD   = true+      , NetBSD    = true+      , Solaris   = true+      , Dragonfly = true+      , Linux     = true+      , Darwin    = true+      , Windows   = false+      , Redox     = false+      , Haiku     = false+      , IOS       = true+      , AIX       = true+      , Hurd      = true+      , Android   = true+      , NoOs      = false -- bad but this should never happen+      }+      os+in++{- Environment variable LDFLAGS for a given configuration -}+let mkLDFlagsGeneral =+  λ(libDirs : List Text) →+  λ(linkLibs : List Text) →+    let flag0 = concatMapSep " " Text (λ(dir : Text) → "-L${dir}") libDirs+    in+    let flag1 = concatMapText Text (λ(dir : Text) → " -l${dir}") linkLibs+    let flag2 = concatMapText Text (λ(dir : Text) → " -Wl,-rpath-link,${dir}") libDirs+    in++    { var = "LDFLAGS", value = flag0 ++ flag1 ++ flag2 }+in++let mkLDFlags =+  λ(libDirs : List Text) →+    mkLDFlagsGeneral libDirs ([] : List Text)+in++let mkLDPath =+  λ(libDirs : List Text) →+    let flag = concatMapSep ":" Text (λ(dir : Text) → dir) libDirs+    in++    { var = "LD_LIBRARY_PATH", value = flag }+in++let mkLDRunPath =+  λ(libDirs : List Text) →+    let flag = concatMapSep ":" Text (λ(dir : Text) → dir) libDirs+    in++    { var = "LD_RUN_PATH", value = flag }+in++let mkStaPath =+  λ(libDirs : List Text) →+    let flag = concatMapSep ":" Text (λ(dir : Text) → dir) libDirs+    in++    { var = "LIBRARY_PATH", value = flag }+in++{- Get the host OS from a configuration. If we are not cross-compiling, we can+   just use the build OS as detected by cpkg+   -}+let osCfg =+  λ(cfg : types.BuildVars) →+    Optional/fold types.TargetTriple cfg.targetTriple types.OS+      (λ(tgt : types.TargetTriple) → tgt.os)+        cfg.buildOS+in++{- Get the host architecture for the build, using the method above -}+let archCfg =+  λ(cfg : types.BuildVars) →+    Optional/fold types.TargetTriple cfg.targetTriple types.Arch+      (λ(tgt : types.TargetTriple) → tgt.arch)+        cfg.buildArch+in+++{- Used to set the PERL5LIB variable to the right thing. This is necessary since+   we install libraries to nonstandard locations.+   -}+let mkPerlLib =+  λ(x : { libDirs : List Text, perlVersion : List Natural, cfg : types.BuildVars }) →+    let os = x.cfg.buildOS+    in+    let arch = x.cfg.buildArch+    in+    let flag = concatMapSep ":" Text (λ(dir : Text) → dir ++ "/site_perl/${showVersion x.perlVersion}/${printArch arch}-${printOS os}/") x.libDirs+    in+    let major = Optional/fold Natural (List/head Natural x.perlVersion) Text (Natural/show) ""+    in++    { var = "PERL${major}LIB", value = flag }+in++let mkIncludePath =+  λ(incls : List Text) →+    let flag = concatMapSep ":" Text (λ(dir : Text) → dir) incls+    in++    { var = "C_INCLUDE_PATH", value = flag }+in++let mkCFlags =+  λ(libDirs : List Text) →+    let flag = concatMapSep " " Text (λ(dir : Text) → "-I${dir}") libDirs+    in++    { var = "CPPFLAGS", value = flag }+in++let mkPkgConfigVar =+  λ(libDirs : List Text) →+    let flag = concatMapSep ":" Text (λ(dir : Text) → "${dir}/pkgconfig") libDirs+    in++    { var = "PKG_CONFIG_PATH", value = flag }+in++{- This is used for GLib/GTK/some of that stuff -}+let mkXdgDataDirs =+  λ(shareDirs : List Text) →+    let flag = concatMapSep ":" Text (λ(dir : Text) → dir) shareDirs+    in++    { var = "XDG_DATA_DIRS", value = flag }+in++let mkPathVar =+  λ(binDirs : List Text) →+    concatMapText Text (λ(dir : Text) → "${dir}:") binDirs+in++let defaultPath =+  λ(cfg : types.BuildVars) →+    if isUnix cfg.buildOS+      then [ { var = "PATH", value = mkPathVar cfg.binDirs ++ "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" } ] : List types.EnvVar+      else [] : List types.EnvVar -- FIXME: handle non-unix case+in++{- Set either LD_LIBRARY_PATH or LIBRARY_PATH depending on whether we are doing+   a static build or not+   -}+let libPath =+  λ(cfg : types.BuildVars) →+    if cfg.static+      then+        mkStaPath cfg.linkDirs+      else+        mkLDPath cfg.linkDirs+in++{- Default environment variables for a given configuration -}+let configEnv =+  λ(linkLibs : List Text) →+  λ(cfg : types.BuildVars) →+    defaultPath cfg # [ mkLDFlagsGeneral cfg.linkDirs linkLibs+                      , mkCFlags cfg.includeDirs+                      , mkPkgConfigVar (cfg.shareDirs # cfg.linkDirs)+                      , libPath cfg+                      , mkLDRunPath cfg.linkDirs+                      , mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,28,1], cfg = cfg } -- TODO: take this as a parameter+                      ]+in++let buildEnv =+  λ(cfg : types.BuildVars) →+    defaultPath cfg # [ mkPkgConfigVar (cfg.shareDirs # cfg.linkDirs)+                      , mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,28,1], cfg = cfg } -- TODO: take this as a parameter+                      , mkLDPath cfg.linkDirs+                      ]+in++let configSome =+  λ(linkLibs : List Text) →+  λ(cfg : types.BuildVars) →+    Some (configEnv linkLibs cfg)+in++{- The most general configuration setup. You probably want to use+   defaultConfigure+   -}+let generalConfigure =+  λ(envVars : List Text → types.BuildVars → Optional (List types.EnvVar)) →+  λ(filename : Text) →+  λ(linkLibs : List Text) →+  λ(extraFlags : List Text) →+  λ(cfg : types.BuildVars) →+    let maybeHost = mkHost cfg.targetTriple+    in+    let modifyArgs = maybeAppend Text maybeHost+    in++    [ mkExe filename+    , call (defaultCall ⫽ { program = "./${filename}"+                          , arguments = modifyArgs [ "--prefix=${cfg.installDir}" ] # extraFlags+                          , environment = envVars linkLibs cfg+                          })+    ]+in++let configureWithFlags =+  generalConfigure configSome "configure" ([] : List Text)++in++let defaultConfigure =+  configureWithFlags ([] : List Text)+in++let configureLinkExtraLibs =+  λ(linkLibs : List Text) →+    generalConfigure configSome "configure" linkLibs ([] : List Text)+in++let mkAclocalPath =+  λ(shareDirs : List Text) →+    let flag = concatMapSep ":" Text (λ(dir : Text) → "${dir}/aclocal") shareDirs+    in++    { var = "ACLOCAL_PATH", value = flag }+in++let configureMkExesExtraFlags =+  λ(x : { bins : List Text, extraFlags : List Text }) →+  λ(cfg : types.BuildVars) →+    mkExes x.bins+      # configureWithFlags x.extraFlags cfg+in++let configureMkExes =+  λ(bins : List Text) →+    configureMkExesExtraFlags { bins = bins, extraFlags = ([] : List Text) }+in++let buildWith =+  λ(envs : List types.EnvVar) →+  λ(cfg : types.BuildVars) →+    [ call (defaultCall ⫽ { program = makeExe cfg.buildOS+                          , arguments = [ "-j${Natural/show cfg.cpus}" ]+                          , environment =+                              Some envs+                          })+    ]+in++let defaultBuild =+  λ(cfg : types.BuildVars) →+    buildWith (buildEnv cfg) cfg+in++let installWith =+  λ(envs : List types.EnvVar) →+  λ(cfg : types.BuildVars) →+    [ call (defaultCall ⫽ { program = makeExe cfg.buildOS+                          , arguments = [ "install" ]+                          , environment =+                              Some envs+                          })+    ]+in++let defaultInstall =+  λ(cfg : types.BuildVars) →+    installWith (buildEnv cfg) cfg+in++let installWithBinaries =+  λ(bins : List Text) →+  λ(installVars : types.BuildVars) →+    defaultInstall installVars+      # symlinkBinaries bins+in++let unbounded =+  λ(x : Text) →+    { name = x+    , bound = types.VersionBound.NoBound {=}+    }+in++let lowerBound =+  λ(pkg : { name : Text, lower : List Natural }) →+    { name = pkg.name+    , bound = types.VersionBound.Lower { lower = pkg.lower }+    }+in++let upperBound =+  λ(pkg : { name : Text, upper : List Natural }) →+    { name = pkg.name+    , bound = types.VersionBound.Upper { upper = pkg.upper }+    }+in++let defaultPackage =+  { configureCommand = defaultConfigure+  , buildCommand     = defaultBuild+  , installCommand   = defaultInstall+  , pkgBuildDeps     = [] : List types.Dep+  , pkgDeps          = [] : List types.Dep+  }+in++let simplePackage =+  λ(pkg : { name : Text, version : List Natural}) →+    defaultPackage ⫽+      { pkgName = pkg.name+      , pkgVersion = pkg.version+      , pkgSubdir = "${pkg.name}-${showVersion pkg.version}"+      }+in++let makeGnuExe =+  λ(pkg : { name : Text, version : List Natural}) →+    simplePackage pkg ⫽+      { pkgUrl = "https://ftp.gnu.org/gnu/${pkg.name}/${pkg.name}-${showVersion pkg.version}.tar.xz"+      , installCommand = installWithBinaries [ "bin/${pkg.name}" ]+      }+in++let makeGnuLibrary =+  λ(pkg : { name : Text, version : List Natural}) →+    simplePackage pkg ⫽+      { pkgUrl = "https://mirrors.ocf.berkeley.edu/gnu/lib${pkg.name}/lib${pkg.name}-${showVersion pkg.version}.tar.xz"+      , pkgSubdir = "lib${pkg.name}-${showVersion pkg.version}"+      }+in++let createDir =+  λ(x : Text) →+    types.Command.CreateDirectory { dir = x }+in++let printCMakeOS =+  λ(os : types.OS) →+    merge+      { FreeBSD   = λ(_ : {}) → "BSD"+      , OpenBSD   = λ(_ : {}) → "BSD"+      , NetBSD    = λ(_ : {}) → "BSD"+      , Solaris   = λ(_ : {}) → "Solaris"+      , Dragonfly = λ(_ : {}) → "BSD"+      , Linux     = λ(_ : {}) → "Linux"+      , Darwin    = λ(_ : {}) → "Darwin"+      , Windows   = λ(_ : {}) → "Windows"+      , Redox     = λ(_ : {}) → "Redox"+      , Haiku     = λ(_ : {}) → "Haiku"+      , IOS       = λ(_ : {}) → "Darwin"+      , AIX       = λ(_ : {}) → "AIX"+      , Hurd      = λ(_ : {}) → "Hurd"+      , Android   = λ(_ : {}) → "Android"+      , NoOs      = λ(_ : {}) → "Generic"+      }+      os+in++let cmakeConfigureGeneral =+  λ(envVars : types.BuildVars → Optional (List types.EnvVar)) →+  λ(flags : List Text) →+  λ(cfg : types.BuildVars) →+    let host =+      Optional/fold types.TargetTriple cfg.targetTriple (List Text)+        (λ(tgt : types.TargetTriple) → ["-DCMAKE_C_COMPILER=${printTargetTriple tgt}-gcc", "-DCMAKE_CXX_COMPILER=${printTargetTriple tgt}-g++"])+          (["-DCMAKE_C_COMPILER=cc", "-DCMAKE_CXX_COMPILER=c++"])+    in+    let system =+      Optional/fold types.TargetTriple cfg.targetTriple (List Text)+        (λ(tgt : types.TargetTriple) → ["-DCMAKE_SYSTEM_NAME=${printCMakeOS tgt.os}"])+          ([] : List Text)+    in++    [ createDir "build"+    , call { program = "cmake"+           , arguments = [ "../", "-DCMAKE_INSTALL_PREFIX:PATH=${cfg.installDir}", "-DCMAKE_MAKE_PROGRAM=${makeExe cfg.buildOS}" ] # host # system # flags+           , environment = envVars cfg+           , procDir = Some "build"+           }+    ]+in++let cmakeEnv =+  λ(cfg : types.BuildVars) →+    [ mkPkgConfigVar (cfg.shareDirs # cfg.linkDirs) ]+      # defaultPath cfg+in++let cmakeSome =+  λ(cfg : types.BuildVars) →+    Some (cmakeEnv cfg)+in++let cmakeConfigureWithFlags =+  cmakeConfigureGeneral cmakeSome+in++let cmakeConfigure =+  cmakeConfigureWithFlags ([] : List Text)+in++let cmakeConfigureNinja =+  λ(cfg : types.BuildVars) →+    let host =+      Optional/fold types.TargetTriple cfg.targetTriple (List Text)+        (λ(tgt : types.TargetTriple) → ["-DCMAKE_C_COMPILER=${printTargetTriple tgt}-gcc", "-DCMAKE_CXX_COMPILER=${printTargetTriple tgt}-g++"])+          ([] : List Text)+    in++    let system =+      Optional/fold types.TargetTriple cfg.targetTriple (List Text)+        (λ(tgt : types.TargetTriple) → ["-DCMAKE_SYSTEM_NAME=${printCMakeOS tgt.os}"])+          ([] : List Text)+    in++    [ createDir "build"+    , call { program = "cmake"+           , arguments = [ "../", "-DCMAKE_INSTALL_PREFIX:PATH=${cfg.installDir}", "-G", "Ninja" ] # host # system+           , environment = defaultEnv+           , procDir = Some "build"+           }+    ]+in++let perlConfigure =+  λ(cfg : types.BuildVars) →++  [ call { program = "perl"+         , arguments = [ "Makefile.PL", "PREFIX=${cfg.installDir}" ]+         , environment = defaultEnv+         , procDir = None Text+         }+  ]+in++let cmakeBuild =+  λ(cfg : types.BuildVars) →+    [ call { program = "cmake"+           , arguments = [ "--build", ".", "--config", "Release", "--", "-j", Natural/show cfg.cpus ]+           , environment = defaultEnv+           , procDir = Some "build"+           }+    ]+in++let cmakeInstall =+  λ(cfg : types.BuildVars) →+    [ call { program = "cmake"+           , arguments = [ "--build", ".", "--target", "install", "--config", "Release" ]+           , environment = defaultEnv+           , procDir = Some "build"+           }+    ]+in++let cmakeInstallWithBinaries =+  λ(bins : List Text) →+  λ(installVars : types.BuildVars) →+    cmakeInstall installVars+      # symlinkBinaries bins+in++let cmakePackage =+  defaultPackage ⫽+    { configureCommand = cmakeConfigure+    , buildCommand     = cmakeBuild+    , installCommand   = cmakeInstall+    , pkgBuildDeps     = [ unbounded "cmake" ]+    }+in++let autogenConfigure =+  λ(cfg : types.BuildVars) →+    [ mkExe "autogen.sh"+    , call (defaultCall ⫽ { program = "./autogen.sh"+                          -- TODO ACLOCAL_PATH ??+                          -- also binary paths+                          })+    ] # defaultConfigure cfg+in++let fullVersion =+  λ(x : { version : List Natural, patch : Natural }) →+    x.version # [x.patch]+in++let mkPyPath =+  λ(version : List Natural) →+  λ(libDirs : List Text) →+    let flag = concatMapSep ":" Text (λ(dir : Text) → "${dir}/python${showVersion version}/site-packages") libDirs+    in++    { var = "PYTHONPATH", value = flag }+in++let mkPy3Path =+  mkPyPath [3,7]+in++{- Write a cross-compilation configuration file for use with meson -}+let mesonCfgFile =+  λ(cfg : types.BuildVars) →+    let prefix =+      Optional/fold types.TargetTriple cfg.targetTriple Text+        (λ(tgt : types.TargetTriple) → "${printTargetTriple tgt}-")+          ""+    in++    "[binaries]\n" +++    "c = '${prefix}gcc'\n" ++ -- FIXME: default to cc/c++ when no cfg.targetTriple is passed+    "cpp = '${prefix}g++'\n" +++    "ar = '${prefix}ar'\n" +++    "strip = '${prefix}strip'\n" +++    "pkgconfig = 'pkg-config'\n" ++++    "[host_machine]\n" +++    "system = '${printOS (osCfg cfg)}'\n" ++ -- TODO: printOSMeson function (w64 -> windows)+    "cpu_family = '${printArch (archCfg cfg)}'\n" +++    "cpu = '${printArch (archCfg cfg)}'\n" +++    "endian = 'little'" -- FIXME parse endianness in Haskell library?+in++let mesonEnv =+  λ(cfg : types.BuildVars) →+    Some [ mkPkgConfigVar cfg.linkDirs+         , { var = "PATH", value = mkPathVar cfg.binDirs ++ "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }+         , mkPy3Path cfg.linkDirs+         , libPath cfg+         , mkLDRunPath cfg.linkDirs+         , mkLDFlags cfg.linkDirs+         , mkCFlags cfg.includeDirs+         , mkPkgConfigVar cfg.linkDirs+         ]+in++let mesonConfigureGeneral =+  λ(envs : types.BuildVars → Optional (List types.EnvVar)) →+  λ(flags : List Text) →+  λ(cfg : types.BuildVars) →+    let crossArgs =+      if cfg.isCross+        then [ "--cross-file", "cross.txt" ]+        else [] : List Text+    in++    [ createDir "build"+    , writeFile { file = "build/cross.txt", contents = mesonCfgFile cfg }+    , call { program = "meson"+           , arguments = [ "--prefix=${cfg.installDir}", ".." ] # crossArgs # flags+           , environment = envs cfg+           , procDir = Some "build"+           }+    ]+in++let mesonConfigureWithFlags =+  mesonConfigureGeneral mesonEnv+in++let mesonConfigure =+  mesonConfigureWithFlags ([] : List Text)+in++let ninjaBuildWith =+  λ(linkLibs : List Text) →+  λ(cfg : types.BuildVars) →+    [ call (defaultCall ⫽ { program = "ninja"+                          , environment = Some [ mkPkgConfigVar cfg.linkDirs+                                               , { var = "PATH", value = mkPathVar cfg.binDirs ++ "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }+                                               , mkPy3Path cfg.linkDirs+                                               , libPath cfg+                                               , mkLDRunPath cfg.linkDirs+                                               , mkLDFlagsGeneral cfg.linkDirs linkLibs+                                               , mkCFlags cfg.includeDirs+                                               , mkPkgConfigVar cfg.linkDirs+                                               ]+                          , procDir = Some "build" }) ]+in++let ninjaBuild =+  ninjaBuildWith ([] : List Text)+in++let ninjaInstall =+  λ(cfg : types.BuildVars) →+    [ call (defaultCall ⫽ { program = "ninja"+                          , environment = Some [ mkPkgConfigVar cfg.linkDirs+                                               , { var = "PATH", value = mkPathVar cfg.binDirs ++ "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }+                                               , mkPy3Path cfg.linkDirs+                                               , libPath cfg+                                               , mkLDRunPath cfg.linkDirs+                                               , mkLDFlags cfg.linkDirs+                                               , mkCFlags cfg.includeDirs+                                               ]+                          , arguments = [ "install" ]+                          , procDir = Some "build"+                          })+    ]+in++let ninjaPackage =+  λ(x : { name : Text, version : List Natural }) →+    simplePackage x ⫽+      { configureCommand = mesonConfigure+      , buildCommand = ninjaBuild+      , installCommand = ninjaInstall+      , pkgBuildDeps = [ unbounded "meson"+                       , unbounded "ninja"+                       ]+      }+in++let copyFiles =+  map { src : Text, dest : Text } types.Command types.Command.CopyFile+in++let ninjaInstallWithPkgConfig =+  λ(fs : List { src : Text, dest : Text }) →+  λ(cfg : types.BuildVars) →+    ninjaInstall cfg # copyFiles fs+in++let doNothing =+  λ(_ : types.BuildVars) → [] : List types.Command+in++let mesonMoves =+  map Text { src : Text, dest : Text} (λ(pcFile : Text) → { src = "build/meson-private/${pcFile}", dest = "lib/pkgconfig/${pcFile}" })+in++let pythonBuild =+  λ(version : List Natural) →+  λ(cfg : types.BuildVars) →+    let major = Optional/fold Natural (List/head Natural version) Text (Natural/show) ""+    in+    let versionString = showVersion version+    in+    [ createDir "${cfg.installDir}/lib/python${versionString}/site-packages"+    , call (defaultCall ⫽ { program = "python${major}"+                          , arguments = [ "setup.py", "build" ]+                          , environment = Some ([ { var = "PYTHONPATH", value = "${cfg.installDir}/lib/python${versionString}/site-packages" }+                                                  , mkPkgConfigVar cfg.linkDirs+                                                  , libPath cfg+                                                  ] # defaultPath cfg)+                          })+    ]+in++let pythonInstall =+  λ(version : List Natural) →+  λ(cfg : types.BuildVars) →+    let major = Optional/fold Natural (List/head Natural version) Text (Natural/show) ""+    in+    let versionString = showVersion version+    in+    [ createDir "${cfg.installDir}/lib/python${versionString}/site-packages"+    , call (defaultCall ⫽ { program = "python${major}"+                          , arguments = [ "setup.py", "install", "--prefix=${cfg.installDir}", "--optimize=1" ]+                          , environment = Some ([ { var = "PYTHONPATH", value = "${cfg.installDir}/lib/python${versionString}/site-packages" }+                                                , mkPkgConfigVar cfg.linkDirs+                                                , libPath cfg+                                                ] # defaultPath cfg)+                          })+    ]+in++let pythonPackage =+  λ(pyVersion : List Natural) →+  λ(x : { name : Text, version : List Natural }) →+    let major = Optional/fold Natural (List/head Natural pyVersion) Text (Natural/show) ""+    in+    simplePackage x ⫽+      { configureCommand = doNothing+      , buildCommand = pythonBuild pyVersion+      , installCommand = pythonInstall pyVersion+      , pkgBuildDeps = [ unbounded "python${major}" ]+      }+in++let python3Build =+  pythonBuild [3,7]+in++let python3Install =+  pythonInstall [3,7]+in++let python3Package =+  pythonPackage [3,7]+in++let python2Package =+  pythonPackage [2,7]+in++{- This is vaguely terrible, but it's needed for GLib for some reason -}+let mkLDPreload =+  λ(libs : List Text) →+    let flag = concatMapSep " " Text (λ(lib : Text) → lib) libs+    in++    { var = "LD_PRELOAD", value = flag }+in++let mkCCVar =+  λ(cfg : types.BuildVars) →+    Optional/fold types.TargetTriple cfg.targetTriple (List types.EnvVar)+      (λ(tgt : types.TargetTriple) → [{ var = "CC", value = "${printTargetTriple tgt}-gcc" }])+        ([] : List types.EnvVar)+in++let squishVersion =+  concatMapText Natural Natural/show+in++let mkCCArg =+  λ(cfg : types.BuildVars) →+    Optional/fold types.TargetTriple cfg.targetTriple (List Text)+      (λ(tgt : types.TargetTriple) → ["CC=${printTargetTriple tgt}-gcc"])+        ([] : List Text)+in++let preloadEnv =+  λ(_ : List Text) →+  λ(cfg : types.BuildVars) →+    Some (defaultPath cfg # [ mkLDFlags cfg.linkDirs+                            , mkCFlags cfg.includeDirs+                            , mkPkgConfigVar cfg.linkDirs+                            , libPath cfg+                            , mkXdgDataDirs cfg.shareDirs+                            , mkLDPreload cfg.preloadLibs+                            , mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,28,1], cfg = cfg } -- TODO: take this as a parameter+                            ])+in++let preloadCfg =+  generalConfigure preloadEnv "configure" ([] : List Text) ([] : List Text)+in++let printEnvVar =+  λ(var : types.EnvVar) →+    "${var.var}=${var.value}"+in++{- This writes + installs a shell script that allows you to use programs+   installed via cpkg with the appropriate environment variables set, since of+   course we install in nonstandard locations+   -}+let mkPyWrapper =+  λ(version : List Natural) →+  λ(binName : Text) →+  λ(cfg : types.BuildVars) →+    let wrapperContents = "${printEnvVar (libPath cfg)} ${printEnvVar (mkPyPath version cfg.linkDirs)}:${cfg.installDir}/lib/python${showVersion version}/site-packages ${cfg.installDir}/bin/${binName} $@"+    in+    let wrapped = "wrapper/${binName}"+    in++    [ createDir "wrapper"+    , writeFile { file = wrapped, contents = wrapperContents }+    , mkExe wrapped+    , copyFile wrapped wrapped+    , symlinkBinary wrapped+    ]+in++let mkPy3Wrapper =+  mkPyWrapper [3,7]+in++let mkPy2Wrapper =+  mkPyWrapper [2,7]+in++let installWithPyWrappers =+  λ(version : List Natural) →+  λ(binNames : List Text) →+  λ(cfg : types.BuildVars) →+    pythonInstall version cfg+      # concatMap Text types.Command (λ(bin : Text) → mkPyWrapper version bin cfg) binNames+in++let installWithPy3Wrappers =+  installWithPyWrappers [3,7]+in++{- This is used to make bash scripts that wrap an executable. Since executables+   are linked against libraries installed in nonstandard places, we wrap them+   with a shell script that sets LD_LIBRARY_PATH appropriately.++   For an example use, see the emacs package.+   -}+let mkLDPathWrapper =+  λ(cfg : types.BuildVars) →+  λ(binName : Text) →+    let wrapper = "${printEnvVar (mkLDPath cfg.linkDirs)}:${cfg.installDir}/lib LD_PRELOAD='${(mkLDPreload cfg.preloadLibs).value}' ${cfg.installDir}/bin/${binName} $@"+    in+    let wrapped = "wrapper/${binName}"+    in++    [ createDir "wrapper"+    , writeFile { file = wrapped, contents = wrapper }+    , mkExe wrapped+    , copyFile wrapped wrapped+    , symlinkBinary wrapped+    ]+in++let installWithWrappers =+  λ(bins : List Text) →+  λ(cfg : types.BuildVars) →+    defaultInstall cfg #+      concatMap Text types.Command (λ(bin : Text) → mkLDPathWrapper cfg bin) bins+in++let underscoreVersion =+  concatMapSep "_" Natural Natural/show+in++let isX64 =+  let true = λ(_ : {}) → True+  in+  let false = λ(_ : {}) → False+  in+  λ(arch : types.Arch) →+    merge+      { X64         = true+      , AArch       = false+      , Arm         = false+      , RISCV64     = false+      , PowerPC     = false+      , PowerPC64   = false+      , PowerPC64le = false+      , Sparc64     = false+      , S390x       = false+      , Alpha       = false+      , M68k        = false+      , Mips        = false+      , MipsEl      = false+      , Mips64      = false+      , Mips64El    = false+      , X86         = false+      , SH4         = false+      , HPPA        = false+      , HPPA64      = false+      }+      arch+in++{ showVersion         = showVersion+, makeGnuLibrary      = makeGnuLibrary+, makeGnuExe          = makeGnuExe+, defaultPackage      = defaultPackage+, unbounded           = unbounded+, lowerBound          = lowerBound+, upperBound          = upperBound+, makeExe             = makeExe+, printArch           = printArch+, printManufacturer   = printManufacturer+, printOS             = printOS+, printTargetTriple   = printTargetTriple+, call                = call+, mkExe               = mkExe+, mkExes              = mkExes+, createDir           = createDir+, mkHost              = mkHost+, defaultConfigure    = defaultConfigure+, defaultBuild        = defaultBuild+, defaultInstall      = defaultInstall+, cmakeConfigure      = cmakeConfigure+, cmakeConfigureGeneral = cmakeConfigureGeneral+, cmakeConfigureWithFlags = cmakeConfigureWithFlags+, cmakeBuild          = cmakeBuild+, cmakeInstall        = cmakeInstall+, cmakePackage        = cmakePackage+, autogenConfigure    = autogenConfigure+, defaultCall         = defaultCall+, defaultEnv          = defaultEnv+, maybeAppend         = maybeAppend+, mkCFlags            = mkCFlags+, mkLDFlags           = mkLDFlags+, mkLDPath            = mkLDPath+, mkLDRunPath         = mkLDRunPath+, mkStaPath           = mkStaPath+, libPath             = libPath+, mkPyPath            = mkPyPath+, mkPy3Path           = mkPy3Path+, mkIncludePath       = mkIncludePath+, isUnix              = isUnix+, defaultPath         = defaultPath+, simplePackage       = simplePackage+, symlinkBinary       = symlinkBinary+, symlink             = symlink+, symlinkBinaries     = symlinkBinaries+, installWithBinaries = installWithBinaries+, configureMkExes     = configureMkExes+, generalConfigure    = generalConfigure+, configureWithFlags  = configureWithFlags+, configureMkExesExtraFlags = configureMkExesExtraFlags+, writeFile           = writeFile+, cmakeInstallWithBinaries = cmakeInstallWithBinaries+, copyFile            = copyFile+, mkPathVar           = mkPathVar+, mkPkgConfigVar      = mkPkgConfigVar+, fullVersion         = fullVersion+, mesonConfigure      = mesonConfigure+, mesonConfigureGeneral = mesonConfigureGeneral+, mesonEnv            = mesonEnv+, mesonConfigureWithFlags = mesonConfigureWithFlags+, ninjaBuild          = ninjaBuild+, ninjaInstall        = ninjaInstall+, ninjaInstallWithPkgConfig = ninjaInstallWithPkgConfig+, ninjaPackage        = ninjaPackage+, doNothing           = doNothing+, perlConfigure       = perlConfigure+, copyFiles           = copyFiles+, mkPerlLib           = mkPerlLib+, mesonMoves          = mesonMoves+, python3Build        = python3Build+, python3Install      = python3Install+, python3Package      = python3Package+, mkLDPreload         = mkLDPreload+, configureLinkExtraLibs = configureLinkExtraLibs+, mkXdgDataDirs       = mkXdgDataDirs+, buildWith           = buildWith+, installWith         = installWith+, mkCCVar             = mkCCVar+, squishVersion       = squishVersion+, osCfg               = osCfg+, archCfg             = archCfg+, mkCCArg             = mkCCArg+, mesonCfgFile        = mesonCfgFile+, python2Package      = python2Package+, configEnv           = configEnv+, configSome          = configSome+, preloadEnv          = preloadEnv+, preloadCfg          = preloadCfg+, printEnvVar         = printEnvVar+, mkPyWrapper         = mkPyWrapper+, mkPy3Wrapper        = mkPy3Wrapper+, mkPy2Wrapper        = mkPy2Wrapper+, installWithPyWrappers = installWithPyWrappers+, installWithPy3Wrappers = installWithPy3Wrappers+, cmakeConfigureNinja = cmakeConfigureNinja+, mkLDPathWrapper     = mkLDPathWrapper+, installWithWrappers = installWithWrappers+, cmakeEnv            = cmakeEnv+, cmakeSome           = cmakeSome+, underscoreVersion   = underscoreVersion+, isX64               = isX64+}
+ dhall/cpkg-types.dhall view
@@ -0,0 +1,120 @@+let OS = < FreeBSD : {}+         | OpenBSD : {}+         | NetBSD : {}+         | Solaris : {}+         | Dragonfly : {}+         | Linux : {}+         | Darwin : {}+         | Windows : {}+         | Redox : {}+         | Haiku : {}+         | IOS : {}+         | AIX : {}+         | Hurd : {}+         | Android : {}+         | NoOs : {}+         >+in++let Arch = < X64 : {}+           | AArch : {}+           | Arm : {}+           | RISCV64 : {}+           | PowerPC : {}+           | PowerPC64 : {}+           | PowerPC64le : {}+           | Sparc64 : {}+           | S390x : {}+           | Alpha : {}+           | M68k : {}+           | Mips : {}+           | MipsEl : {}+           | Mips64 : {}+           | Mips64El : {}+           | X86 : {}+           | SH4 : {}+           | HPPA : {}+           | HPPA64 : {}+           >+in++let Manufacturer = < Unknown : {}+                   | Apple : {}+                   | IBM : {}+                   | PC : {}+                   >+in++let ABI = < GNU : {}+          | GNUabi64 : {}+          | GNUeabi : {}+          | GNUeabihf : {}+          | GNUspe : {}+          | MinGw : {}+          >+in++let TargetTriple = { arch : Arch+                   , manufacturer : Optional Manufacturer+                   , os : OS+                   , abi : Optional ABI+                   }+in++let BuildVars = { installDir : Text+                , currentDir : Text+                , targetTriple : Optional TargetTriple+                , isCross : Bool+                , includeDirs : List Text+                , preloadLibs : List Text+                , shareDirs : List Text+                , linkDirs : List Text+                , binDirs : List Text+                , buildOS : OS+                , buildArch : Arch+                , static : Bool+                , cpus : Natural+                }+in++let VersionBound = < Lower : { lower : List Natural }+                   | Upper : { upper : List Natural }+                   | LowerUpper : { lower : List Natural, upper : List Natural }+                   | NoBound : {} >+in++let Dep = { name : Text, bound : VersionBound }+in++let EnvVar = { var : Text, value : Text }+in++let Proc = { program : Text+           , arguments : List Text+           , environment : Optional (List EnvVar)+           , procDir : Optional Text+           }+in++let Command = < CreateDirectory : { dir : Text }+              | MakeExecutable : { file : Text }+              | Call : Proc+              | SymlinkBinary : { file : Text }+              | Symlink : { tgt : Text, linkName : Text }+              | Write : { file : Text, contents : Text }+              | CopyFile : { src : Text, dest : Text }+              >+in++{ OS            = OS+, BuildVars     = BuildVars+, VersionBound  = VersionBound+, Dep           = Dep+, Arch          = Arch+, Manufacturer  = Manufacturer+, ABI           = ABI+, TargetTriple  = TargetTriple+, Command       = Command+, EnvVar        = EnvVar+, Proc          = Proc+}
+ pkgs/pkg-set.dhall view
@@ -0,0 +1,2875 @@+{- Dhall prelue imports -}+let concatMapSep = https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/Prelude/Text/concatMapSep+in++{- cpkg prelude imports -}+let types = ../dhall/cpkg-types.dhall+in++let prelude = ../dhall/cpkg-prelude.dhall+in++{- gnupg: https://www.gnupg.org/ -}+let gpgPackage =+  λ(x : { name : Text, version : List Natural }) →+    prelude.simplePackage x ⫽+      { pkgUrl = "https://gnupg.org/ftp/gcrypt/${x.name}/${x.name}-${prelude.showVersion x.version}.tar.bz2" }+in++let gnupg =+  λ(v : List Natural) →+    gpgPackage { name = "gnupg", version = v } ⫽+      { pkgDeps = [ prelude.lowerBound { name = "npth", lower = [1,2] }+                  , prelude.lowerBound { name = "libgpg-error", lower = [1,24] }+                  , prelude.lowerBound { name = "libgcrypt", lower = [1,7,0] }+                  , prelude.lowerBound { name = "libassuan", lower = [2,5,0] }+                  , prelude.lowerBound { name = "libksba", lower = [1,3,4] }+                  ]+      , configureCommand = prelude.configureMkExes [ "tests/inittests", "tests/runtest", "tests/pkits/inittests" ]+      , installCommand = prelude.installWithBinaries [ "bin/gpg" ]+      }+in++let npth =+  λ(v : List Natural) →+    gpgPackage { name = "npth", version = v }+in++let libgpgError =+  λ(v : List Natural) →+    gpgPackage { name = "libgpg-error", version = v }+in++let libgcrypt =+  λ(v : List Natural) →+    gpgPackage { name = "libgcrypt", version = v } ⫽+      { pkgDeps = [ prelude.lowerBound { name = "libgpg-error", lower = [1,25] } ] }+in++let libassuan =+  λ(v : List Natural) →+    gpgPackage { name = "libassuan", version = v } ⫽+      { pkgDeps = [ prelude.lowerBound { name = "libgpg-error", lower = [1,24] } ] }+in++let libksba =+  λ(v : List Natural) →+    gpgPackage { name = "libksba", version = v } ⫽+      { pkgDeps = [ prelude.lowerBound { name = "libgpg-error", lower = [1,8] } ] }+in++{- musl: https://www.musl-libc.org/ -}+let musl =+  λ(v : List Natural) →+    prelude.simplePackage { name = "musl", version = v } ⫽+      { pkgUrl = "https://www.musl-libc.org/releases/musl-${prelude.showVersion v}.tar.gz"+      , installCommand = prelude.installWithBinaries [ "bin/musl-gcc" ]+      , configureCommand = prelude.configureMkExes [ "tools/install.sh" ]+      }+in++let binutils =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "binutils", version = v } ⫽+      { pkgUrl = "https://mirrors.ocf.berkeley.edu/gnu/binutils/binutils-${prelude.showVersion v}.tar.xz"+      , configureCommand = prelude.configureMkExes [ "mkinstalldirs" ]+      , installCommand =+          prelude.installWithBinaries [ "bin/ar", "bin/as", "bin/ld", "bin/strip", "bin/strings", "bin/readelf", "bin/objdump", "bin/nm", "bin/ranlib" ]+      }+in++let bison =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "bison", version = v } ⫽+      { configureCommand = prelude.configureMkExes [ "build-aux/move-if-change" ]+      , installCommand = prelude.installWithBinaries [ "bin/bison", "bin/yacc" ]+      , pkgBuildDeps = [ prelude.unbounded "m4" ]+      }+in++{- cmake https://cmake.org/ -}+let cmake =+  λ(cfg : { version : List Natural, patch : Natural }) →+    let patchString = Natural/show cfg.patch+    in+    let versionString = prelude.showVersion cfg.version+    in+    let cmakeConfigure =+      λ(cfg : types.BuildVars) →+        prelude.configureMkExesExtraFlags { bins = [ "bootstrap" ]+                                          , extraFlags = [ "--parallel=${Natural/show cfg.cpus}" ]+                                          } cfg+    in++    prelude.defaultPackage ⫽+      { pkgName = "cmake"+      , pkgVersion = prelude.fullVersion cfg+      , pkgUrl = "https://cmake.org/files/v${versionString}/cmake-${versionString}.${patchString}.tar.gz"+      , pkgSubdir = "cmake-${versionString}.${patchString}"+      , configureCommand = cmakeConfigure+      , installCommand =+          λ(cfg : types.BuildVars) →+            let wrapper = "CMAKE_ROOT=${cfg.installDir}/share/cmake-${versionString}/ ${cfg.installDir}/bin/cmake $@"+            in+            let wrapped = "wrapper/cmake"+            in+            prelude.defaultInstall cfg+              # [ prelude.createDir "wrapper"+                , prelude.writeFile { file = wrapped, contents = wrapper }+                , prelude.mkExe wrapped+                , prelude.copyFile wrapped wrapped+                , prelude.symlinkBinary wrapped+                ]+      }+in++let curl =+  λ(v : List Natural) →+    prelude.simplePackage { name = "curl", version = v } ⫽+      { pkgUrl = "https://curl.haxx.se/download/curl-${prelude.showVersion v}.tar.xz"+      , installCommand = prelude.installWithBinaries [ "bin/curl" ]+      , pkgDeps = [ prelude.unbounded "zlib" ]+      }+in++let dbus =+  λ(v : List Natural) →+    prelude.simplePackage { name = "dbus", version = v } ⫽+      { pkgUrl = "https://dbus.freedesktop.org/releases/dbus/dbus-${prelude.showVersion v}.tar.gz"+      , pkgDeps = [ prelude.unbounded "expat"+                  , prelude.unbounded "libselinux"+                  ]+      , configureCommand = prelude.configureLinkExtraLibs [ "pcre" ]+      }+in++let fltk =+  λ(cfg : { version : List Natural, patch : Natural }) →++    let versionString = prelude.showVersion cfg.version+    in+    let patchString = Natural/show cfg.patch+    in++    prelude.defaultPackage ⫽+      { pkgName = "fltk"+      , pkgVersion = prelude.fullVersion cfg+      , pkgUrl = "http://fltk.org/pub/fltk/${versionString}/fltk-${versionString}-${patchString}-source.tar.bz2"+      , pkgSubdir = "fltk-${versionString}-${patchString}"+      }+in++let gawk =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "gawk", version = v } ⫽+      { configureCommand = prelude.configureMkExes [ "install-sh", "extension/build-aux/install-sh" ]+      , installCommand = prelude.installWithBinaries [ "bin/gawk", "bin/awk" ]+      }+in++let gc =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "gc", version = v } ⫽+        { pkgUrl = "https://github.com/ivmai/bdwgc/releases/download/v${versionString}/gc-${versionString}.tar.gz"+        , pkgDeps = [ prelude.unbounded "libatomic_ops" ]+        }+in++let libatomic_ops =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "libatomic_ops", version = v } ⫽+        { pkgUrl = "https://github.com/ivmai/libatomic_ops/releases/download/v${versionString}/libatomic_ops-${versionString}.tar.gz" }+in++let git =+  λ(v : List Natural) →+    prelude.simplePackage { name = "git", version = v } ⫽+      { pkgUrl = "https://mirrors.edge.kernel.org/pub/software/scm/git/git-${prelude.showVersion v}.tar.xz"+      , configureCommand = prelude.configureMkExes [ "check_bindir" ]+      , installCommand = prelude.installWithBinaries [ "bin/git" ]+      , pkgBuildDeps = [ prelude.unbounded "gettext" ]+      }+in++let glibc =+  let buildDir =+    Some "build"+  in++  let glibcConfigure =+    λ(cfg : types.BuildVars) →++      let maybeHost = prelude.mkHost cfg.targetTriple+      in+      let modifyArgs = prelude.maybeAppend Text maybeHost+      in++      prelude.mkExes+        [ "configure", "scripts/mkinstalldirs", "scripts/rellns-sh" ]+          # [ prelude.createDir "build"+            , prelude.call { program = "../configure"+                           , arguments = modifyArgs [ "--prefix=${cfg.installDir}" ]+                           , environment = prelude.defaultEnv+                           , procDir = buildDir+                           }+            ]+  in++  let glibcBuild =+    λ(cfg : types.BuildVars) →+      [ prelude.call { program = prelude.makeExe cfg.buildOS+                     , arguments = [ "-j${Natural/show cfg.cpus}" ]+                     , environment = prelude.defaultEnv+                     , procDir = buildDir+                     }+      ]+  in++  let glibcInstall =+    λ(cfg : types.BuildVars) →+      [ prelude.call { program = prelude.makeExe cfg.buildOS+                     , arguments = [ "install" ]+                     , environment = prelude.defaultEnv+                     , procDir = buildDir+                     }+      ]+  in++  λ(v : List Natural) →+    prelude.defaultPackage ⫽+      { pkgName = "glibc"+      , pkgVersion = v+      , pkgUrl = "http://mirror.keystealth.org/gnu/libc/glibc-${prelude.showVersion v}.tar.xz"+      , pkgSubdir = "glibc-${prelude.showVersion v}"+      , configureCommand = glibcConfigure+      , buildCommand = glibcBuild+      , installCommand = glibcInstall+      , pkgBuildDeps = [ prelude.unbounded "bison", prelude.unbounded "gawk" ]+      }+in++let gmp =+  λ(v : List Natural) →+    prelude.simplePackage { name = "gmp", version = v } ⫽+      { pkgUrl = "https://gmplib.org/download/gmp/gmp-${prelude.showVersion v}.tar.xz"+      , configureCommand = prelude.configureMkExes [ "mpn/m4-ccas" ]+      , pkgBuildDeps = [ prelude.unbounded "m4" ]+      -- TODO: run 'make check'?+      }+in++let harfbuzz =+  let symlinkHarfbuzz =+    λ(h : Text) →+      prelude.symlink "include/harfbuzz/${h}" "include/${h}"+  in++  λ(v : List Natural) →+    prelude.simplePackage { name = "harfbuzz", version = v } ⫽+      { pkgUrl = "https://www.freedesktop.org/software/harfbuzz/release/harfbuzz-${prelude.showVersion v}.tar.bz2"+      , pkgDeps = [ prelude.unbounded "freetype-prebuild"+                  , prelude.unbounded "glib"+                  ]+      , configureCommand = prelude.configureLinkExtraLibs [ "pcre", "z" ]+      , installCommand =+          λ(cfg : types.BuildVars) →+            prelude.defaultInstall cfg+              # [ symlinkHarfbuzz "hb-aat-layout.h"+                , symlinkHarfbuzz "hb-aat.h"+                , symlinkHarfbuzz "hb-blob.h"+                , symlinkHarfbuzz "hb-buffer.h"+                , symlinkHarfbuzz "hb-common.h"+                , symlinkHarfbuzz "hb-deprecated.h"+                , symlinkHarfbuzz "hb-face.h"+                , symlinkHarfbuzz "hb-font.h"+                , symlinkHarfbuzz "hb-ft.h"+                , symlinkHarfbuzz "hb-glib.h"+                , symlinkHarfbuzz "hb-icu.h"+                , symlinkHarfbuzz "hb-map.h"+                , symlinkHarfbuzz "hb-ot-color.h"+                , symlinkHarfbuzz "hb-ot-font.h"+                , symlinkHarfbuzz "hb-ot-layout.h"+                , symlinkHarfbuzz "hb-ot-math.h"+                , symlinkHarfbuzz "hb-ot-name.h"+                , symlinkHarfbuzz "hb-ot-shape.h"+                , symlinkHarfbuzz "hb-ot-var.h"+                , symlinkHarfbuzz "hb-ot.h"+                , symlinkHarfbuzz "hb-set.h"+                , symlinkHarfbuzz "hb-shape-plan.h"+                , symlinkHarfbuzz "hb-shape.h"+                , symlinkHarfbuzz "hb-subset.h"+                , symlinkHarfbuzz "hb-unicode.h"+                , symlinkHarfbuzz "hb-version.h"+                , symlinkHarfbuzz "hb.h"+                ]+      }+in++let jpegTurbo =+  λ(v : List Natural) →+    prelude.cmakePackage ⫽+      { pkgName = "libjpeg-turbo"+      , pkgVersion = v+      , pkgUrl = "https://downloads.sourceforge.net/libjpeg-turbo/libjpeg-turbo-${prelude.showVersion v}.tar.gz"+      , pkgSubdir = "libjpeg-turbo-${prelude.showVersion v}"+      , pkgBuildDeps = [ prelude.unbounded "cmake"+                       , prelude.unbounded "nasm"+                       ]+      }+in++let libuv =+  λ(v : List Natural) →+    prelude.defaultPackage ⫽+      { pkgName = "libuv"+      , pkgVersion = v+      , pkgUrl = "https://dist.libuv.org/dist/v${prelude.showVersion v}/libuv-v${prelude.showVersion v}.tar.gz"+      , pkgSubdir = "libuv-v${prelude.showVersion v}"+      , configureCommand = prelude.autogenConfigure+      }+in++let nasm =+  λ(v : List Natural) →+    prelude.simplePackage { name = "nasm", version = v } ⫽+      { pkgUrl = "http://www.nasm.us/pub/nasm/releasebuilds/${prelude.showVersion v}/nasm-${prelude.showVersion v}.tar.xz"+      , installCommand = prelude.installWithBinaries [ "bin/nasm", "bin/ndisasm" ]+      }+in++let ncurses =+  λ(v : List Natural) →+    prelude.simplePackage { name = "ncurses", version = v } ⫽+      { pkgUrl = "https://ftp.gnu.org/pub/gnu/ncurses/ncurses-${prelude.showVersion v}.tar.gz"+      , configureCommand = prelude.configureWithFlags [ "--disable-stripping", "--with-shared", "--enable-widec" ]+      -- we disable stripping because otherwise the script fails during cross-compilation+      -- enable-widec is necessary because util-linux uses libncursesw+      }+in++let pcre2 =+  λ(v : List Natural) →+    prelude.simplePackage { name = "pcre2", version = v } ⫽+      { pkgUrl = "https://ftp.pcre.org/pub/pcre/pcre2-${prelude.showVersion v}.tar.bz2" }+in++let pcre =+  λ(v : List Natural) →+    prelude.simplePackage { name = "pcre", version = v } ⫽+      { pkgUrl = "https://ftp.pcre.org/pub/pcre/pcre-${prelude.showVersion v}.tar.bz2" }+in++let perl5 =+  let perlConfigure =+    λ(cfg : types.BuildVars) →+      [ prelude.mkExe "Configure"+      , prelude.call (prelude.defaultCall ⫽ { program = "./Configure"+                                            , arguments = [ "-des", "-Dprefix=${cfg.installDir}" ] # (if cfg.static then [] : List Text else [ "-Duseshrplib" ])+                                            })+      ]+  in++  λ(v : List Natural) →+    let major = Optional/fold Natural (List/head Natural v) Text (Natural/show) ""+    in++    prelude.simplePackage { name = "perl", version = v } ⫽+      { pkgUrl = "https://www.cpan.org/src/${major}.0/perl-${prelude.showVersion v}.tar.gz"+      , configureCommand = perlConfigure+      , installCommand =+        λ(cfg : types.BuildVars) →+          let libperlFile =+            if cfg.static+              then "libperl.a"+              else "libperl.so"+          in++          prelude.installWithBinaries [ "bin/perl", "bin/cpan" ] cfg+            # [ prelude.symlink "lib/${prelude.showVersion v}/${prelude.printArch cfg.buildArch}-${prelude.printOS cfg.buildOS}/CORE/${libperlFile}" "lib/${libperlFile}" ]+      }+in++let libpng =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libpng", version = v } ⫽+      { pkgUrl = "https://download.sourceforge.net/libpng/libpng-${prelude.showVersion v}.tar.xz"+      , pkgDeps = [ prelude.unbounded "zlib" ]+      }+in++let sed =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "sed", version = v } -- TODO: require pcre?+in++let tar =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "tar", version = v }+in++let unistring =+  λ(v : List Natural) →+    prelude.makeGnuLibrary { name = "unistring", version = v }+in++let valgrind =+  λ(v : List Natural) →+    prelude.simplePackage { name = "valgrind", version = v } ⫽+      { pkgUrl = "http://www.valgrind.org/downloads/valgrind-${prelude.showVersion v}.tar.bz2"+      , installCommand = prelude.installWithBinaries [ "bin/valgrind" ]+      , configureCommand = prelude.configureMkExes [ "auxprogs/make_or_upd_vgversion_h" ]+      }+in++let vim =+  λ(v : List Natural) →+    prelude.defaultPackage ⫽+      { pkgName = "vim"+      , pkgVersion = v+      , pkgUrl = "http://ftp.vim.org/vim/unix/vim-${prelude.showVersion v}.tar.bz2"+      , pkgSubdir = "vim${prelude.squishVersion v}"+      , configureCommand =+          prelude.configureMkExesExtraFlags { bins = [ "src/configure", "src/auto/configure", "src/which.sh" ]+                                            , extraFlags = [ "--enable-gui=no"+                                                           , "--enable-pythoninterp"+                                                           ]+                                            }+      , installCommand =+          λ(cfg : types.BuildVars) →+            let mkLibDynload =+              λ(libs : List Text) →+                concatMapSep ":" Text (λ(dir : Text) → "${dir}/python2.7/lib-dynload") libs+            in+            let mkPython =+              λ(libs : List Text) →+                concatMapSep ":" Text (λ(dir : Text) → "${dir}/python2.7/:${dir}/python2.7/lib-dynload") libs+            in+            -- TODO: change LD_RUN_PATH during build instead...+            -- or alternately, symlink lib-dynload stuff when installing python2??+            let wrapper = "LD_LIBRARY_PATH=${mkLibDynload cfg.linkDirs} PYTHONPATH=${mkPython cfg.linkDirs} ${cfg.installDir}/bin/vim $@"+            in+            let wrapped = "wrapper/vim"+            in++            prelude.installWithBinaries [ "bin/xxd" ] cfg+              # [ prelude.createDir "wrapper"+                , prelude.writeFile { file = wrapped, contents = wrapper }+                , prelude.mkExe wrapped+                , prelude.copyFile wrapped wrapped+                , prelude.symlinkBinary wrapped+                ]+      , pkgDeps = [ prelude.unbounded "ncurses"+                  , prelude.unbounded "libXpm"+                  , prelude.unbounded "libXt"+                  , prelude.unbounded "python2"+                  ]+      }+in++let xz =+  λ(v : List Natural) →+    prelude.simplePackage { name = "xz", version = v } ⫽+      { pkgUrl = "https://tukaani.org/xz/xz-${prelude.showVersion v}.tar.xz"+      , installCommand = prelude.installWithBinaries [ "bin/xz" ]+      }+in++let zlib =+  λ(v : List Natural) →++    let zlibConfigure =+      λ(cfg : types.BuildVars) →++        let host =+          prelude.mkCCVar cfg+        in++        [ prelude.mkExe "configure"+        , prelude.call (prelude.defaultCall ⫽ { program = "./configure"+                                              , arguments = [ "--prefix=${cfg.installDir}" ]+                                              , environment = Some (host # [ { var = "PATH", value = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" } ])+                                              })+        ]+    in++    prelude.simplePackage { name = "zlib", version = v } ⫽+      { pkgUrl = "http://www.zlib.net/zlib-${prelude.showVersion v}.tar.xz"+      , configureCommand = zlibConfigure+      }+in++let gettext =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "gettext", version = v } ⫽+      { installCommand = prelude.installWithBinaries [ "bin/gettext", "bin/msgfmt" ] }+in++let gzip =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "gzip", version = v }+in++let wget =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "wget", version = v } ⫽+      { pkgUrl = "https://ftp.gnu.org/gnu/wget/wget-${prelude.showVersion v}.tar.gz"+      , pkgDeps = [ prelude.unbounded "gnutls" ]+      , pkgBuildDeps = [ prelude.unbounded "perl" ]+      , configureCommand = prelude.configureMkExes [ "doc/texi2pod.pl" ]+      , installCommand =+          prelude.installWithWrappers [ "wget" ]+      }+in++let gnutls =+  λ(cfg : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion cfg.version+    in++    prelude.simplePackage { name = "gnutls", version = prelude.fullVersion cfg } ⫽+      { pkgUrl = "https://www.gnupg.org/ftp/gcrypt/gnutls/v${versionString}/gnutls-${versionString}.${Natural/show cfg.patch}.tar.xz"+      , pkgDeps = [ prelude.lowerBound { name = "nettle", lower = [3,1] }+                  , prelude.unbounded "unistring"+                  , prelude.lowerBound { name = "libtasn1", lower = [4,9] }+                  , prelude.lowerBound { name = "p11-kit", lower = [0,23,1] }+                  ]+      , configureCommand =+	λ(cfg : types.BuildVars) →+	  prelude.mkExes [ "src/gen-mech-list.sh" ]+	    # prelude.configureLinkExtraLibs [ "nettle", "hogweed" ] cfg+      }+in++let lapack =+  λ(v : List Natural) →+    prelude.cmakePackage ⫽+      { pkgName = "lapack"+      , pkgVersion = v+      , pkgUrl = "http://www.netlib.org/lapack/lapack-${prelude.showVersion v}.tar.gz"+      , pkgSubdir = "lapack-${prelude.showVersion v}"+      , pkgBuildDeps = [ prelude.unbounded "cmake" ]+      }+in++let cairo =+  let symlinkCairo =+    λ(h : Text) →+      prelude.symlink "include/cairo/${h}" "include/${h}"+  in++  λ(v : List Natural) →+    prelude.simplePackage { name = "cairo", version = v } ⫽+     { pkgUrl = "https://www.cairographics.org/releases/cairo-${prelude.showVersion v}.tar.xz"+     , pkgDeps = [ prelude.lowerBound { name = "pixman", lower = [0,30,0] }+                 , prelude.lowerBound { name = "freetype", lower = [9,7,3] }+                 , prelude.lowerBound { name = "fontconfig", lower = [2,2,95] }+                 , prelude.unbounded "libXext"+                 ]+     , installCommand =+        λ(cfg : types.BuildVars) →+          prelude.defaultInstall cfg #+            [ symlinkCairo "cairo-deprecated.h"+            , symlinkCairo "cairo-features.h"+            , symlinkCairo "cairo-ft.h"+            , symlinkCairo "cairo-gobject.h"+            , symlinkCairo "cairo-pdf.h"+            , symlinkCairo "cairo-ps.h"+            , symlinkCairo "cairo-script-interpreter.h"+            , symlinkCairo "cairo-script.h"+            , symlinkCairo "cairo-svg.h"+            , symlinkCairo "cairo-version.h"+            , symlinkCairo "cairo-xcb.h"+            , symlinkCairo "cairo-xlib-xrender.h"+            , symlinkCairo "cairo-xlib.h"+            , symlinkCairo "cairo.h"+            ]+     }+in++let pycairo =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.python2Package { name = "pycairo", version = v } ⫽+      { pkgUrl = "https://github.com/pygobject/pycairo/releases/download/v${versionString}/pycairo-${versionString}.tar.gz"+      , pkgDeps = [ prelude.unbounded "cairo" ]+      }+in++let libnettle =+  λ(v : List Natural) →+    prelude.simplePackage { name = "nettle", version = v } ⫽+      { pkgUrl = "https://ftp.gnu.org/gnu/nettle/nettle-${prelude.showVersion v}.tar.gz"+      , pkgBuildDeps = [ prelude.unbounded "m4" ]+      }+in++let m4 =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "m4", version = v } ⫽+      -- FIXME: this is in place until there's a mechanism to patch...+      { buildCommand = prelude.doNothing+      , installCommand = prelude.doNothing+      }+in++let nginx =+  λ(v : List Natural) →+    prelude.simplePackage { name = "nginx", version = v } ⫽+      { pkgUrl = "http://nginx.org/download/nginx-${prelude.showVersion v}.tar.gz"+      , pkgDeps = [ prelude.unbounded "zlib", prelude.unbounded "pcre2" ]+      }+in++let openssl =+  let opensslCfgVars =+    λ(cfg : types.BuildVars) →+      Some (prelude.mkCCVar cfg # prelude.configEnv ([] : List Text) cfg)+  in++  λ(v : List Natural) →+    prelude.simplePackage { name = "openssl", version = v } ⫽+      { pkgUrl = "https://www.openssl.org/source/openssl-${prelude.showVersion v}a.tar.gz"+      , configureCommand =+          λ(cfg : types.BuildVars) →+            let sharedFlag =+              if cfg.static+                then "no-shared"+                else "shared"+            in+            [ prelude.mkExe "Configure"+            , prelude.call (prelude.defaultCall ⫽ { program = "./Configure"+                                                  , arguments = [ "--prefix=${cfg.installDir}", "gcc", sharedFlag ] -- FIXME: gcc platform doesn't support shared libraries+                                                  , environment = opensslCfgVars cfg+                                                  })+            ]+      , pkgSubdir = "openssl-${prelude.showVersion v}a"+      , pkgBuildDeps = [ prelude.unbounded "perl" ]+      }+in++let libssh2 =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libssh2", version = v } ⫽+      { pkgUrl = "https://www.libssh2.org/download/libssh2-${prelude.showVersion v}.tar.gz" }+in++let giflib =+  λ(v : List Natural) →+    prelude.simplePackage { name = "giflib", version = v } ⫽+      { pkgUrl = "https://downloads.sourceforge.net/giflib/giflib-${prelude.showVersion v}.tar.bz2" }+in++let emacs =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "emacs", version = v } ⫽+      { pkgDeps = [ prelude.unbounded "giflib"+                  , prelude.unbounded "libXaw"+                  , prelude.unbounded "libpng"+                  , prelude.unbounded "libjpeg-turbo"+                  , prelude.unbounded "ncurses"+                  , prelude.unbounded "gtk3"+                  , prelude.unbounded "libotf"+                  , prelude.unbounded "m17n-lib"+                  , prelude.unbounded "gnutls"+                  , prelude.unbounded "libXft"+                  , prelude.unbounded "dbus"+                  ]+      , configureCommand = prelude.configureMkExesExtraFlags+          { bins = [ "build-aux/move-if-change", "build-aux/update-subdirs" ]+          , extraFlags = [ "--with-tiff=no"+                         , "--with-libotf"+                         , "--with-m17n-flt"+                         , "--with-gnutls"+                         , "--with-xft"+                         , "--with-dbus"+                         ]+          }+      , installCommand =+          prelude.installWithWrappers [ "emacs" ]+      }+in++let which =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "which", version = v } ⫽+      { pkgUrl = "https://ftp.gnu.org/gnu/which/which-${prelude.showVersion v}.tar.gz" }+in++let automake =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "automake", version = v } ⫽+      { pkgBuildDeps = [ prelude.lowerBound { name =  "autoconf", lower = [2,65] } ]+      , installCommand = prelude.installWithBinaries [ "bin/automake", "bin/aclocal" ]+      }+in++let autoconf =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "autoconf", version = v } ⫽+      { pkgBuildDeps = [ prelude.lowerBound { name =  "m4", lower = [1,4,16] } ]+      , installCommand = prelude.installWithBinaries [ "bin/autoconf", "bin/autoheader", "bin/autom4te", "bin/autoreconf" ]+      }+in++let python =+  λ(v : List Natural) →+    let major = Optional/fold Natural (List/head Natural v) Text (Natural/show) ""+    in+    let versionString = prelude.showVersion v+    in++    prelude.simplePackage { name = "python${major}", version = v } ⫽+      { pkgUrl = "https://www.python.org/ftp/python/${versionString}/Python-${versionString}.tar.xz"+      , pkgSubdir = "Python-${versionString}"+      , configureCommand =+        λ(cfg : types.BuildVars) →+          let staticFlag =+            if cfg.static+              then [] : List Text+              else [ "--enable-shared" ]+          in+          prelude.configureWithFlags ([ "--build=${prelude.printArch cfg.buildArch}" ] # staticFlag) cfg+          -- "--enable-optimizations" (takes forever)+      , pkgDeps = [ prelude.unbounded "libffi" ]+      , installCommand = prelude.installWithBinaries [ "bin/python${major}" ]+      -- , installCommand =+          -- prelude.installWithWrappers [ "python${major}" ]+      }+in++let lua =+  λ(v : List Natural) →+    let printLuaOS =+      λ(os : types.OS) →+        merge+          { FreeBSD   = λ(_ : {}) → "freebsd"+          , OpenBSD   = λ(_ : {}) → "bsd"+          , NetBSD    = λ(_ : {}) → "bsd"+          , Solaris   = λ(_ : {}) → "solaris"+          , Dragonfly = λ(_ : {}) → "bsd"+          , Linux     = λ(_ : {}) → "linux"+          , Darwin    = λ(_ : {}) → "macosx"+          , Windows   = λ(_ : {}) → "mingw"+          , Redox     = λ(_ : {}) → "generic"+          , Haiku     = λ(_ : {}) → "generic"+          , IOS       = λ(_ : {}) → "generic"+          , AIX       = λ(_ : {}) → "generic"+          , Hurd      = λ(_ : {}) → "generic"+          , Android   = λ(_ : {}) → "generic"+          , NoOs      = λ(_ : {}) → "c89"+          }+          os+    in++    let luaBuild =+      λ(cfg : types.BuildVars) →+        let cc = prelude.mkCCArg cfg+        in++        let ldflags =+          (prelude.mkLDFlags cfg.linkDirs).value+        in++        let cflags =+          (prelude.mkCFlags cfg.includeDirs).value+        in++        let os =+          prelude.osCfg cfg+        in++        [ prelude.call (prelude.defaultCall ⫽ { program = "make"+                                              , arguments = cc # [ printLuaOS os, "MYLDFLAGS=${ldflags}", "MYCFLAGS=${cflags}", "MYLIBS=-lncurses", "-j${Natural/show cfg.cpus}" ]+                                              })+        ]+    in++    let luaInstall =+      λ(cfg : types.BuildVars) →+        [ prelude.call (prelude.defaultCall ⫽ { program = "make"+                                              , arguments = [ "install", "INSTALL_TOP=${cfg.installDir}" ]+                                              })+        ]+          # prelude.symlinkBinaries [ "bin/lua", "bin/luac" ]+    in++    prelude.simplePackage { name = "lua", version = v } ⫽+      { pkgUrl = "http://www.lua.org/ftp/lua-${prelude.showVersion v}.tar.gz"+      , configureCommand = prelude.doNothing+      , buildCommand = luaBuild+      , installCommand = luaInstall+      , pkgDeps = [ prelude.unbounded "readline"+                  , prelude.unbounded "ncurses"+                  ]+      }+in++let libtasn1 =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libtasn1", version = v } ⫽+      { pkgUrl = "https://ftp.gnu.org/gnu/libtasn1/libtasn1-${prelude.showVersion v}.tar.gz" }+in++let p11kit =+  λ(v : List Natural) →+    prelude.simplePackage { name = "p11-kit", version = v } ⫽+      { pkgUrl = "https://github.com/p11-glue/p11-kit/releases/download/${prelude.showVersion v}/p11-kit-${prelude.showVersion v}.tar.gz"+      , pkgDeps = [ prelude.lowerBound { name = "libffi", lower = [3,0,0] }+                  , prelude.unbounded "libtasn1"+                  ]+      }+in++let libffi =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libffi", version = v } ⫽+      { pkgUrl = "https://sourceware.org/ftp/libffi/libffi-${prelude.showVersion v}.tar.gz" }+in++let gdb =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "gdb", version = v } ⫽+      { configureCommand = prelude.configureMkExes [ "mkinstalldirs" ] }+in++let libtool =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "libtool", version = v } ⫽+      { pkgUrl = "http://ftpmirror.gnu.org/libtool/libtool-${prelude.showVersion v}.tar.gz"+      , pkgBuildDeps = [ prelude.lowerBound { name =  "m4", lower = [1,4,16] } ]+      }+in++let pkg-config =+  λ(v : List Natural) →+    prelude.simplePackage { name = "pkg-config", version = v } ⫽+      { pkgUrl = "https://pkg-config.freedesktop.org/releases/pkg-config-${prelude.showVersion v}.tar.gz"+      , installCommand = prelude.installWithBinaries [ "bin/pkg-config" ]+      }+in++let qrencode =+  λ(v : List Natural) →+    prelude.simplePackage { name = "qrencode", version = v } ⫽+      { pkgUrl = "https://fukuchi.org/works/qrencode/qrencode-${prelude.showVersion v}.tar.gz"+      , configureCommand = prelude.configureWithFlags [ "--without-tools" ]+      }+in++let readline =+  λ(v : List Natural) →+    prelude.simplePackage { name = "readline", version = v } ⫽+      { pkgUrl = "https://ftp.gnu.org/gnu/readline/readline-${prelude.showVersion v}.tar.gz" } -- TODO: should this depend on ncurses?+in++let pixman =+  λ(v : List Natural) →+    prelude.simplePackage { name = "pixman", version = v } ⫽+      { pkgUrl = "https://www.cairographics.org/releases/pixman-${prelude.showVersion v}.tar.gz"+      , pkgDeps = [ prelude.unbounded "libpng" ]+      }+in++let freetype-shared =+  λ(x : { name : Text, version : List Natural }) →+    let versionString = prelude.showVersion x.version+    in++    prelude.simplePackage x ⫽+      { pkgUrl = "https://download.savannah.gnu.org/releases/freetype/freetype-${versionString}.tar.gz"+      , configureCommand = prelude.configureMkExes [ "builds/unix/configure" ]+      , pkgSubdir = "freetype-${versionString}"+      , pkgBuildDeps = [ prelude.unbounded "sed" ]+      , installCommand =+          λ(cfg : types.BuildVars) →+            prelude.defaultInstall cfg+              # [ prelude.symlink "include/freetype2/ft2build.h" "include/ft2build.h"+                , prelude.symlink "include/freetype2/freetype" "include/freetype"+                ]+      }+in++let freetype-prebuild =+  λ(v : List Natural) →+    freetype-shared { name = "freetype-prebuild", version = v } ⫽ -- FIXME: for some reason a zlib dep here breaks harfbuzz???+      { pkgDeps = [ prelude.unbounded "zlib"+                  , prelude.unbounded "libpng"+                  ]+      }+in++let freetype =+  λ(v : List Natural) →+    freetype-shared { name = "freetype", version = v } ⫽+      { pkgDeps = [ prelude.unbounded "zlib"+                  , prelude.unbounded "harfbuzz"+                  , prelude.unbounded "libpng"+                  ]+      , configureCommand = prelude.configureMkExesExtraFlags { bins = [ "builds/unix/configure" ]+                                                             , extraFlags = [ "--enable-freetype-config" ]+                                                             }+      }+in++let sdl2 =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v+    in++    prelude.simplePackage { name = "sdl2", version = v } ⫽+      { pkgUrl = "https://www.libsdl.org/release/SDL2-${versionString}.tar.gz"+      , pkgSubdir = "SDL2-${versionString}"+      }+in++let imageMagick =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v+    in+    let major = Optional/fold Natural (List/head Natural v) Text (Natural/show) ""+    in++    prelude.simplePackage { name = "imagemagick", version = v } ⫽+      { pkgUrl = "https://imagemagick.org/download/ImageMagick-${versionString}-21.tar.xz"+      , pkgSubdir = "ImageMagick-${versionString}-21"+      , installCommand =+          λ(cfg : types.BuildVars) →+            prelude.defaultInstall cfg+              # [ prelude.symlink "include/ImageMagick-${major}/MagickWand" "include/wand" ]+      }+in++let gtk2 =+  let gtkEnv =+    λ(cfg : types.BuildVars) →+      prelude.defaultPath cfg # [ { var = "LDFLAGS", value = (prelude.mkLDFlags cfg.linkDirs).value ++ " -lpcre -lfribidi" }+                                , prelude.mkCFlags cfg.includeDirs+                                , prelude.mkPkgConfigVar cfg.linkDirs+                                , prelude.libPath cfg+                                , prelude.mkLDRunPath cfg.linkDirs+                                , prelude.mkXdgDataDirs cfg.shareDirs+                                , prelude.mkLDPreload cfg.preloadLibs+                                ]+  in+  let gtkConfig =+    λ(cfg : types.BuildVars) →+      [ prelude.mkExe "configure"+      , prelude.call (prelude.defaultCall ⫽ { program = "./configure"+                                            , arguments = [ "--prefix=${cfg.installDir}" ]+                                            , environment = Some (gtkEnv cfg)+                                            })+      ]+  in++  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in++    prelude.simplePackage { name = "gtk2", version = prelude.fullVersion x } ⫽+      { pkgUrl = "http://ftp.gnome.org/pub/gnome/sources/gtk+/${versionString}/gtk+-${fullVersion}.tar.xz"+      , pkgSubdir = "gtk+-${fullVersion}"+      , pkgDeps = [ prelude.lowerBound { name = "cairo", lower = [1,6] }+                  , prelude.lowerBound { name = "pango", lower = [1,20] }+                  , prelude.lowerBound { name = "atk", lower = [1,29,2] }+                  , prelude.lowerBound { name = "glib", lower = [2,28,0] }+                  , prelude.lowerBound { name = "gdk-pixbuf", lower = [2,38,0] }+                  ]+      , buildCommand =+          λ(cfg : types.BuildVars) →+            prelude.buildWith (gtkEnv cfg) cfg+      , configureCommand = gtkConfig+      , installCommand =+          λ(cfg : types.BuildVars) →+            prelude.defaultInstall cfg #+              [ prelude.symlink "include/gdk-pixbuf-2.0/gdk-pixbuf" "include/gdk-pixbuf" ]+      }+in++let mkXProto =+  λ(name : Text) →+  λ(v : List Natural) →+    prelude.simplePackage { name = name, version = v } ⫽+      { pkgUrl = "https://www.x.org/releases/individual/proto/${name}-${prelude.showVersion v}.tar.bz2" }+in++let xproto =+  mkXProto "xproto"+in++let renderproto =+  mkXProto "renderproto"+in++let randrproto =+  mkXProto "randrproto"+in++let scrnsaverproto =+  mkXProto "scrnsaverproto"+in++let recordproto =+  mkXProto "recordproto"+in++let xf86vidmodeproto =+  mkXProto "xf86vidmodeproto"+in++let glproto =+  mkXProto "glproto"+in++let dri2proto =+  mkXProto "dri2proto"+in++let pango =+  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in++    let pangoCfgFile =+      ''+      option('enable_docs',+            description: 'Build API reference for Pango using GTK-Doc',+            type: 'boolean',+            value: false)+      option('gir',+            description: 'Build the GObject introspection data for Pango',+            type: 'boolean',+            value: false)+      ''+    in+    let no_gir =+      λ(cfg : types.BuildVars) →+        if cfg.isCross+          then+            [ prelude.writeFile { file = "meson_options.txt", contents = pangoCfgFile } ]+          else+            ([] : List types.Command)+    in++    prelude.simplePackage { name = "pango", version = prelude.fullVersion x } ⫽+      { pkgUrl = "http://ftp.gnome.org/pub/GNOME/sources/pango/${versionString}/pango-${fullVersion}.tar.xz"+      , configureCommand =+          λ(cfg : types.BuildVars) →+            no_gir cfg+              # prelude.mesonConfigure cfg+      , buildCommand = prelude.ninjaBuild+      , installCommand =+          λ(cfg : types.BuildVars) →+            prelude.ninjaInstallWithPkgConfig (prelude.mesonMoves [ "pango.pc", "pangocairo.pc", "pangoft2.pc" ]) cfg+              # [ prelude.symlink "include/pango-1.0/pango" "include/pango" ]+      , pkgBuildDeps = [ prelude.lowerBound { name = "meson", lower = [0,48,0] }+                       , prelude.unbounded "gobject-introspection"+                       ]+      , pkgDeps = [ prelude.lowerBound { name = "fontconfig", lower = [2,11,91] }+                  , prelude.lowerBound { name = "cairo", lower = [1,12,10] }+                  , prelude.lowerBound { name = "fribidi", lower = [0,19,7] }+                  , prelude.lowerBound { name = "harfbuzz", lower = [1,4,2] }+                  , prelude.unbounded "libXrender"+                  , prelude.unbounded "libxcb"+                  ]+      }+in++let libxml2 =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libxml2", version = v } ⫽+     { pkgUrl = "http://xmlsoft.org/sources/libxml2-${prelude.showVersion v}.tar.gz"+     -- TODO: don't depend on python via flag or something+     , pkgDeps = [ prelude.unbounded "zlib"+                 , prelude.unbounded "xz"+                 ]+     , pkgBuildDeps = [ prelude.unbounded "python2" ]+     }+in++let shared-mime-info =+  λ(v : List Natural) →+    prelude.simplePackage { name = "shared-mime-info", version = v } ⫽+     { pkgUrl = "http://freedesktop.org/~hadess/shared-mime-info-${prelude.showVersion v}.tar.xz"+     , buildCommand =+        λ(cfg : types.BuildVars) →+          [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS+                                                , environment = Some (prelude.defaultPath cfg # [ prelude.libPath cfg+                                                                                                , prelude.mkLDRunPath cfg.linkDirs+                                                                                                , prelude.mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,28,1], cfg = cfg }+                                                                                                ])+                                                })+          ]+     , pkgDeps = [ prelude.unbounded "glib"+                 , prelude.unbounded "libxml2"+                 ]+     , pkgBuildDeps = [ prelude.lowerBound { name = "intltool", lower = [0,35,0] }+                      , prelude.unbounded "sed"+                      , prelude.unbounded "gettext"+                      ]+     }+in++let intltool =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "intltool", version = v } ⫽+      { pkgUrl = "https://launchpad.net/intltool/trunk/${versionString}/+download/intltool-${versionString}.tar.gz"+      , configureCommand =+          λ(cfg : types.BuildVars) →+            [ prelude.mkExe "configure"+            , prelude.call (prelude.defaultCall ⫽ { program = "./configure"+                                                  , arguments = [ "--prefix=${cfg.installDir}" ]+                                                  , environment = Some (prelude.defaultPath cfg+                                                      # [ prelude.mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,28,1], cfg = cfg } ])+                                                  })+            ]+    , pkgDeps = [ prelude.unbounded "XML-Parser" ]+    , pkgBuildDeps = [ prelude.upperBound { name = "perl", upper = [5,30] } ] -- lower bound: 5.8.1+    }+in++let gdk-pixbuf =+  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in++    let gdkInstall =+      λ(fs : List { src : Text, dest : Text }) →+      λ(cfg : types.BuildVars) →+        [ prelude.call (prelude.defaultCall ⫽ { program = "ninja"+                                              , environment = Some [ prelude.mkPkgConfigVar cfg.linkDirs+                                                                   , { var = "PATH", value = prelude.mkPathVar cfg.binDirs ++ ":${cfg.currentDir}/gdk-pixbuf-${fullVersion}/build/gdk-pixbuf:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }+                                                                   , prelude.mkPy3Path cfg.linkDirs+                                                                   , prelude.libPath cfg+                                                                   , prelude.mkLDRunPath cfg.linkDirs+                                                                   , prelude.mkLDFlags cfg.linkDirs+                                                                   , prelude.mkCFlags cfg.includeDirs+                                                                   ]+                                              , arguments = [ "install" ]+                                              , procDir = Some "build"+                                              })+        , prelude.symlink "include/gdk-pixbuf-2.0/gdk-pixbuf" "include/gdk-pixbuf"+        ] # prelude.copyFiles fs+    in++    prelude.simplePackage { name = "gdk-pixbuf", version = prelude.fullVersion x } ⫽+      { pkgUrl = "http://ftp.gnome.org/pub/GNOME/sources/gdk-pixbuf/${versionString}/gdk-pixbuf-${fullVersion}.tar.xz"+      , configureCommand = prelude.mesonConfigure+      , buildCommand = prelude.ninjaBuild+      , installCommand =+          gdkInstall (prelude.mesonMoves [ "gdk-pixbuf-2.0.pc" ])+      , pkgDeps = [ prelude.unbounded "glib"+                  , prelude.unbounded "libjpeg-turbo"+                  , prelude.unbounded "libpng"+                  , prelude.unbounded "gobject-introspection"+                  , prelude.unbounded "shared-mime-info"+                  , prelude.unbounded "libX11"+                  ]+      }+in++let xmlParser =+  λ(v : List Natural) →+    prelude.simplePackage { name = "XML-Parser", version = v } ⫽+     { pkgUrl = "https://cpan.metacpan.org/authors/id/T/TO/TODDR/XML-Parser-${prelude.showVersion v}.tar.gz"+     , configureCommand = prelude.perlConfigure+     , pkgBuildDeps = [ prelude.unbounded "perl" ]+     , pkgDeps = [ prelude.unbounded "expat" ]+     }+in++let meson =+  λ(v : List Natural) →+    prelude.simplePackage { name = "meson", version = v } ⫽+      { pkgUrl = "https://github.com/mesonbuild/meson/archive/${prelude.showVersion v}.tar.gz"+      , configureCommand =+          λ(cfg : types.BuildVars) →+            prelude.python3Install cfg # prelude.mkPy3Wrapper "meson" cfg+      , buildCommand = prelude.doNothing+      , installCommand = prelude.doNothing+      , pkgDeps = [ prelude.unbounded "python3" ]+      }+in++let ninja =+  let ninjaConfigure =+    λ(cfg : types.BuildVars) →+      [ prelude.mkExe "configure.py"+      , prelude.mkExe "src/inline.sh"+      , prelude.call (prelude.defaultCall ⫽ { program = "./configure.py"+                                            , arguments = [ "--bootstrap" ]+                                            })+      ]+  in++  let ninjaInstall =+    λ(cfg : types.BuildVars) →+      [ prelude.copyFile "ninja" "bin/ninja"+      , prelude.symlinkBinary "bin/ninja"+      ]+  in++  λ(v : List Natural) →+    prelude.simplePackage { name = "ninja", version = v } ⫽+      { pkgUrl = "https://github.com/ninja-build/ninja/archive/v${prelude.showVersion v}.tar.gz"+      , configureCommand = ninjaConfigure+      , buildCommand = prelude.doNothing+      , installCommand = ninjaInstall+      , pkgBuildDeps = [ prelude.unbounded "python2" ]+      }+in++let fontconfig =+  λ(v : List Natural) →+    prelude.simplePackage { name = "fontconfig", version = v } ⫽+      { pkgUrl = "https://www.freedesktop.org/software/fontconfig/release/fontconfig-${prelude.showVersion v}.tar.bz2"+      , pkgDeps = [ prelude.unbounded "freetype"+                  , prelude.unbounded "expat"+                  , prelude.unbounded "util-linux"+                  ]+      , pkgBuildDeps = [ prelude.unbounded "gperf" ]+      }+in++let util-linux =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+      prelude.simplePackage { name = "util-linux", version = v } ⫽+        { pkgUrl = "https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v${versionString}/util-linux-${versionString}.tar.xz"+        , configureCommand = prelude.configureWithFlags [ "--disable-makeinstall-chown" -- otherwise we'd need sudo permissions+                                                        , "--disable-bash-completion"+                                                        , "--disable-pylibmount" -- easier for cross-compiling+                                                        , "--without-tinfo" -- can't figure out what tinfo is or how to supply it when cross compiling+                                                        ]+        , pkgDeps = [ prelude.unbounded "ncurses" ]+        }+in++let fribidi =+  λ(v : List Natural) →+    prelude.simplePackage { name = "fribidi", version = v } ⫽+      { pkgUrl = "https://github.com/fribidi/fribidi/releases/download/v${prelude.showVersion v}/fribidi-${prelude.showVersion v}.tar.bz2" }+in++let gobject-introspection =+  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in++    prelude.simplePackage { name = "gobject-introspection", version = prelude.fullVersion x } ⫽+      { pkgUrl = "https://download.gnome.org/sources/gobject-introspection/${versionString}/gobject-introspection-${fullVersion}.tar.xz"+      , pkgBuildDeps = [ prelude.unbounded "flex" ]+      , configureCommand = prelude.configureLinkExtraLibs [ "pcre", "gobject-2.0", "gio-2.0" ]+      , pkgDeps = [ prelude.lowerBound { name = "glib", lower = [2,58,0] } ]+      }+in++let flex =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v+    in++    prelude.simplePackage { name = "flex", version = v } ⫽+      { pkgUrl = "https://github.com/westes/flex/releases/download/v${versionString}/flex-${versionString}.tar.gz"+      , pkgBuildDeps = [ prelude.unbounded "m4"+                       , prelude.unbounded "bison"+                       ]+      }+in++let glib =+  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in++    let glibConfigure =+      λ(cfg : types.BuildVars) →+        let crossArgs =+          if cfg.isCross+            then [ "--cross-file", "cross.txt" ]+            else [] : List Text+        in++        [ prelude.createDir "build"+        , prelude.writeFile { file = "build/cross.txt", contents = prelude.mesonCfgFile cfg }+        , prelude.call { program = "meson"+                       , arguments = [ "--prefix=${cfg.installDir}", "..", "-Dselinux=false" ] # crossArgs+                       , environment = Some [ prelude.mkPkgConfigVar cfg.linkDirs+                                            , { var = "PATH", value = prelude.mkPathVar cfg.binDirs ++ "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }+                                            , { var = "LDFLAGS", value = (prelude.mkLDFlags cfg.linkDirs).value ++ " -lpcre" }+                                            , prelude.mkPy3Path cfg.linkDirs+                                            , prelude.libPath cfg+                                            , prelude.mkCFlags cfg.includeDirs+                                            , prelude.mkPkgConfigVar cfg.linkDirs+                                            ]+                       , procDir = Some "build"+                       }+        ]++    in++    let symlinkGio =+      λ(h : Text) →+        prelude.symlink "include/glib-2.0/gio/${h}" "include/gio/${h}"+    in++    let symlinkGunix =+      λ(h : Text) →+        prelude.symlink "include/gio-unix-2.0/gio/${h}" "include/gio/${h}"+    in++    prelude.simplePackage { name = "glib", version = prelude.fullVersion x } ⫽+      { pkgUrl = "http://ftp.gnome.org/pub/gnome/sources/glib/${versionString}/glib-${fullVersion}.tar.xz"+      , configureCommand = glibConfigure+      , buildCommand =+        λ(cfg : types.BuildVars) →+          prelude.ninjaBuild cfg+            # prelude.mkExes [ "build/gobject/glib-mkenums"+                             , "build/gobject/glib-genmarshal"+                             , "build/gio/gdbus-2.0/codegen/gdbus-codegen"+                             , "build/glib-gettextize"+                             ]+      , installCommand =+          λ(cfg : types.BuildVars) →+            let libDir = "lib/${prelude.printArch cfg.buildArch}-${prelude.printOS cfg.buildOS}-gnu"+            in++            prelude.ninjaInstallWithPkgConfig (prelude.mesonMoves [ "glib-2.0.pc"+                                                                  , "gobject-2.0.pc"+                                                                  , "gio-2.0.pc"+                                                                  , "gio-unix-2.0.pc" -- TODO: only on unix+                                                                  , "gmodule-no-export-2.0.pc"+                                                                  , "gmodule-export-2.0.pc"+                                                                  , "gmodule-2.0.pc"+                                                                  , "gthread-2.0.pc"+                                                                  ]) cfg++              # [ prelude.symlink "${libDir}/libglib-2.0.so" "lib/libglib-2.0.so"+                , prelude.symlink "${libDir}/libgobject-2.0.so" "lib/libgobject-2.0.so"+                , prelude.symlink "${libDir}/libgio-2.0.so" "lib/libgio-2.0.so"+                , prelude.symlink "${libDir}/libgmodule-2.0.so" "lib/libgmodule-2.0.so"+                , prelude.symlink "${libDir}/libgmodule-2.0.so.0" "lib/libgmodule-2.0.so.0"+                , prelude.symlink "${libDir}/libglib-2.0.so.0" "lib/libglib-2.0.so.0"+                , prelude.symlink "${libDir}/glib-2.0/include/glibconfig.h" "include/glibconfig.h"+                , prelude.symlink "include/glib-2.0/glib" "include/glib"+                , prelude.symlink "include/glib-2.0/gobject" "include/gobject"+                , prelude.symlink "include/glib-2.0/glib.h" "include/glib.h"+                , prelude.symlink "include/glib-2.0/glib-object.h" "include/glib-object.h"+                , prelude.symlink "include/glib-2.0/glib-unix.h" "include/glib-unix.h" -- TODO: only symlink on unix+                , prelude.symlink "include/glib-2.0/gmodule.h" "include/gmodule.h"+                , symlinkGio "gaction.h"+                , symlinkGio "gactiongroup.h"+                , symlinkGio "gactiongroupexporter.h"+                , symlinkGio "gactionmap.h"+                , symlinkGio "gappinfo.h"+                , symlinkGio "gapplication.h"+                , symlinkGio "gapplicationcommandline.h"+                , symlinkGio "gasyncinitable.h"+                , symlinkGio "gasyncresult.h"+                , symlinkGio "gbufferedinputstream.h"+                , symlinkGio "gbufferedoutputstream.h"+                , symlinkGio "gbytesicon.h"+                , symlinkGio "gcancellable.h"+                , symlinkGio "gcharsetconverter.h"+                , symlinkGio "gcontenttype.h"+                , symlinkGio "gconverter.h"+                , symlinkGio "gconverterinputstream.h"+                , symlinkGio "gconverteroutputstream.h"+                , symlinkGio "gcredentials.h"+                , symlinkGio "gdatagrambased.h"+                , symlinkGio "gdatainputstream.h"+                , symlinkGio "gdataoutputstream.h"+                , symlinkGio "gdbusactiongroup.h"+                , symlinkGio "gdbusaddress.h"+                , symlinkGio "gdbusauthobserver.h"+                , symlinkGio "gdbusconnection.h"+                , symlinkGio "gdbuserror.h"+                , symlinkGio "gdbusinterface.h"+                , symlinkGio "gdbusinterfaceskeleton.h"+                , symlinkGio "gdbusintrospection.h"+                , symlinkGio "gdbusmenumodel.h"+                , symlinkGio "gdbusmessage.h"+                , symlinkGio "gdbusmethodinvocation.h"+                , symlinkGio "gdbusnameowning.h"+                , symlinkGio "gdbusnamewatching.h"+                , symlinkGio "gdbusobject.h"+                , symlinkGio "gdbusobjectmanager.h"+                , symlinkGio "gdbusobjectmanagerclient.h"+                , symlinkGio "gdbusobjectmanagerserver.h"+                , symlinkGio "gdbusobjectproxy.h"+                , symlinkGio "gdbusobjectskeleton.h"+                , symlinkGio "gdbusproxy.h"+                , symlinkGio "gdbusserver.h"+                , symlinkGio "gdbusutils.h"+                , symlinkGio "gdrive.h"+                , symlinkGio "gdtlsclientconnection.h"+                , symlinkGio "gdtlsconnection.h"+                , symlinkGio "gdtlsserverconnection.h"+                , symlinkGio "gemblem.h"+                , symlinkGio "gemblemedicon.h"+                , symlinkGio "gfile.h"+                , symlinkGio "gfileattribute.h"+                , symlinkGio "gfileenumerator.h"+                , symlinkGio "gfileicon.h"+                , symlinkGio "gfileinfo.h"+                , symlinkGio "gfileinputstream.h"+                , symlinkGio "gfileiostream.h"+                , symlinkGio "gfilemonitor.h"+                , symlinkGio "gfilenamecompleter.h"+                , symlinkGio "gfileoutputstream.h"+                , symlinkGio "gfilterinputstream.h"+                , symlinkGio "gfilteroutputstream.h"+                , symlinkGio "gicon.h"+                , symlinkGio "ginetaddress.h"+                , symlinkGio "ginetaddressmask.h"+                , symlinkGio "ginetsocketaddress.h"+                , symlinkGio "ginitable.h"+                , symlinkGio "ginputstream.h"+                , symlinkGio "gio-autocleanups.h"+                , symlinkGio "gio.h"+                , symlinkGio "gioenums.h"+                , symlinkGio "gioenumtypes.h"+                , symlinkGio "gioerror.h"+                , symlinkGio "giomodule.h"+                , symlinkGio "gioscheduler.h"+                , symlinkGio "giostream.h"+                , symlinkGio "giotypes.h"+                , symlinkGio "glistmodel.h"+                , symlinkGio "gliststore.h"+                , symlinkGio "gloadableicon.h"+                , symlinkGio "gmemoryinputstream.h"+                , symlinkGio "gmemoryoutputstream.h"+                , symlinkGio "gmenu.h"+                , symlinkGio "gmenuexporter.h"+                , symlinkGio "gmenumodel.h"+                , symlinkGio "gmount.h"+                , symlinkGio "gmountoperation.h"+                , symlinkGio "gnativevolumemonitor.h"+                , symlinkGio "gnetworkaddress.h"+                , symlinkGio "gnetworking.h"+                , symlinkGio "gnetworkmonitor.h"+                , symlinkGio "gnetworkservice.h"+                , symlinkGio "gnotification.h"+                , symlinkGio "goutputstream.h"+                , symlinkGio "gpermission.h"+                , symlinkGio "gpollableinputstream.h"+                , symlinkGio "gpollableoutputstream.h"+                , symlinkGio "gpollableutils.h"+                , symlinkGio "gpropertyaction.h"+                , symlinkGio "gproxy.h"+                , symlinkGio "gproxyaddress.h"+                , symlinkGio "gproxyaddressenumerator.h"+                , symlinkGio "gproxyresolver.h"+                , symlinkGio "gremoteactiongroup.h"+                , symlinkGio "gresolver.h"+                , symlinkGio "gresource.h"+                , symlinkGio "gseekable.h"+                , symlinkGio "gsettings.h"+                , symlinkGio "gsettingsbackend.h"+                , symlinkGio "gsettingsschema.h"+                , symlinkGio "gsimpleaction.h"+                , symlinkGio "gsimpleactiongroup.h"+                , symlinkGio "gsimpleasyncresult.h"+                , symlinkGio "gsimpleiostream.h"+                , symlinkGio "gsimplepermission.h"+                , symlinkGio "gsimpleproxyresolver.h"+                , symlinkGio "gsocket.h"+                , symlinkGio "gsocketaddress.h"+                , symlinkGio "gsocketaddressenumerator.h"+                , symlinkGio "gsocketclient.h"+                , symlinkGio "gsocketconnectable.h"+                , symlinkGio "gsocketconnection.h"+                , symlinkGio "gsocketcontrolmessage.h"+                , symlinkGio "gsocketlistener.h"+                , symlinkGio "gsocketservice.h"+                , symlinkGio "gsrvtarget.h"+                , symlinkGio "gsubprocess.h"+                , symlinkGio "gsubprocesslauncher.h"+                , symlinkGio "gtask.h"+                , symlinkGio "gtcpconnection.h"+                , symlinkGio "gtcpwrapperconnection.h"+                , symlinkGio "gtestdbus.h"+                , symlinkGio "gthemedicon.h"+                , symlinkGio "gthreadedsocketservice.h"+                , symlinkGio "gtlsbackend.h"+                , symlinkGio "gtlscertificate.h"+                , symlinkGio "gtlsclientconnection.h"+                , symlinkGio "gtlsconnection.h"+                , symlinkGio "gtlsdatabase.h"+                , symlinkGio "gtlsfiledatabase.h"+                , symlinkGio "gtlsinteraction.h"+                , symlinkGio "gtlspassword.h"+                , symlinkGio "gtlsserverconnection.h"+                , symlinkGio "gvfs.h"+                , symlinkGio "gvolume.h"+                , symlinkGio "gvolumemonitor.h"+                , symlinkGio "gzlibcompressor.h"+                , symlinkGio "gzlibdecompressor.h"+                -- TODO: only do this on unix+                , symlinkGunix "gdesktopappinfo.h"+                , symlinkGunix "gfiledescriptorbased.h"+                , symlinkGunix "gunixconnection.h"+                , symlinkGunix "gunixcredentialsmessage.h"+                , symlinkGunix "gunixfdlist.h"+                , symlinkGunix "gunixfdmessage.h"+                , symlinkGunix "gunixinputstream.h"+                , symlinkGunix "gunixmounts.h"+                , symlinkGunix "gunixoutputstream.h"+                , symlinkGunix "gunixsocketaddress.h"+                ]++      , pkgBuildDeps = [ prelude.unbounded "meson"+                       , prelude.unbounded "ninja"+                       ]+      , pkgDeps = [ prelude.unbounded "util-linux"+                  , prelude.unbounded "pcre" -- >= 8.31+                  , prelude.unbounded "libffi"+                  , prelude.unbounded "zlib"+                  , prelude.unbounded "dbus"+                  ]+      }+in++let atk =+  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in++    prelude.ninjaPackage { name = "atk", version = prelude.fullVersion x } ⫽+      { pkgUrl = "https://ftp.gnome.org/pub/gnome/sources/atk/${versionString}/atk-${fullVersion}.tar.xz"+      , pkgBuildDeps = [ prelude.unbounded "gobject-introspection"+                       , prelude.unbounded "gettext"+                       ] -- TODO: disable introspection?+      , pkgDeps = [ prelude.unbounded "glib" ]+      , installCommand =+          prelude.ninjaInstallWithPkgConfig [{ src = "build/atk.pc", dest = "lib/pkgconfig/atk.pc" }]+      }+in++let re2c =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v+    in++    prelude.simplePackage { name = "re2c", version = v } ⫽+      { pkgUrl = "https://github.com/skvadrik/re2c/releases/download/${versionString}/re2c-${versionString}.tar.gz" }+in++let chickenScheme =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v+    in++    let printChickenOS =+      λ(os : types.OS) →+        merge+          { FreeBSD   = λ(_ : {}) → "bsd"+          , OpenBSD   = λ(_ : {}) → "bsd"+          , NetBSD    = λ(_ : {}) → "bsd"+          , Solaris   = λ(_ : {}) → "solaris"+          , Dragonfly = λ(_ : {}) → "bsd"+          , Linux     = λ(_ : {}) → "linux"+          , Darwin    = λ(_ : {}) → "macosx"+          , Windows   = λ(_ : {}) → "mingw"+          , Haiku     = λ(_ : {}) → "haiku"+          , IOS       = λ(_ : {}) → "ios"+          , AIX       = λ(_ : {}) → "aix"+          , Hurd      = λ(_ : {}) → "hurd"+          , Android   = λ(_ : {}) → "android"+          , Redox     = λ(_ : {}) → "error: no port for Redox OS"+          , NoOs      = λ(_ : {}) → "error: no port for no OS"+          }+          os+    in++    let chickenBuild =+      λ(cfg : types.BuildVars) →+        let cc =+          Optional/fold types.TargetTriple cfg.targetTriple (List Text)+            (λ(tgt : types.TargetTriple) → [ "C_COMPILER=${prelude.printTargetTriple tgt}-gcc" ])+              ([] : List Text)+        in+        let os =+          prelude.osCfg cfg+        in+        [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS+                                              , arguments = cc # [ "PLATFORM=${printChickenOS os}", "PREFIX=${cfg.installDir}" ]+                                              })+        , prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS+                                              , arguments = cc # [ "PLATFORM=${printChickenOS os}", "PREFIX=${cfg.installDir}", "install" ]+                                              })+        ]+          # prelude.symlinkBinaries [ "bin/csc", "bin/chicken-install", "bin/csi" ]+    in++    prelude.simplePackage { name = "chicken-scheme", version = v } ⫽+      { pkgUrl = "https://code.call-cc.org/releases/${versionString}/chicken-${versionString}.tar.gz"+      , configureCommand = prelude.doNothing+      , buildCommand = chickenBuild+      , installCommand = prelude.doNothing+      , pkgSubdir = "chicken-${versionString}"+      }+in++let xcb-proto =+  λ(v : List Natural) →+    prelude.simplePackage { name = "xcb-proto", version = v } ⫽+      { pkgUrl = "https://xorg.freedesktop.org/archive/individual/xcb/xcb-proto-${prelude.showVersion v}.tar.bz2" }+in++let libxcb =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libxcb", version = v } ⫽+      { pkgUrl = "https://xorg.freedesktop.org/archive/individual/xcb/libxcb-${prelude.showVersion v}.tar.bz2"+      , pkgDeps = [ prelude.lowerBound { name = "xcb-proto", lower = [1,13] }+                  , prelude.unbounded "libXau"+                  , prelude.unbounded "libpthread-stubs"+                  , prelude.unbounded "libXdmcp"+                  ]+      }+in++let libpthread-stubs =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libpthread-stubs", version = v } ⫽+      { pkgUrl = "https://www.x.org/archive/individual/xcb/libpthread-stubs-${prelude.showVersion v}.tar.bz2" }+in++let libXdmcp =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libXdmcp", version = v } ⫽+      { pkgUrl = "https://www.x.org/archive/individual/lib/libXdmcp-${prelude.showVersion v}.tar.bz2"+      , pkgDeps = [ prelude.unbounded "xproto" ]+      }+in++let libXau =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libXau", version = v } ⫽+      { pkgUrl = "https://www.x.org/archive/individual/lib/libXau-${prelude.showVersion v}.tar.bz2"+      , pkgDeps = [ prelude.unbounded "xproto" ]+      }+in++let xorgConfigure =+  prelude.configureWithFlags [ "--disable-malloc0returnsnull" ] -- necessary for cross-compilation+in++let mkXLib =+  λ(name : Text) →+  λ(v : List Natural) →+    prelude.simplePackage { name = name, version = v } ⫽+      { pkgUrl = "https://www.x.org/releases/individual/lib/${name}-${prelude.showVersion v}.tar.bz2"+      , configureCommand = xorgConfigure+      }+in++let mkXLibDeps =+  λ(x : { name : Text, deps : List types.Dep }) →+  λ(v : List Natural) →+    mkXLib x.name v ⫽+      { pkgDeps = x.deps }+in++let mkXUtil =+  λ(name : Text) →+  λ(v : List Natural) →+    prelude.simplePackage { name = name, version = v } ⫽+      { pkgUrl = "https://www.x.org/releases/individual/util/${name}-${prelude.showVersion v}.tar.bz2" }+in++let libXrender =+  mkXLibDeps { name = "libXrender"+             , deps = [ prelude.unbounded "xproto"+                      , prelude.unbounded "renderproto"+                      , prelude.unbounded "libX11"+                      ]+             }+in++let util-macros =+  mkXUtil "util-macros"+in++let libXft =+  mkXLibDeps { name = "libXft"+             , deps = [ prelude.unbounded "freetype"+                      , prelude.unbounded "fontconfig"+                      , prelude.unbounded "libXrender"+                      , prelude.unbounded "libX11"+                      ]+             }+in++let kbproto =+  mkXProto "kbproto"+in++let libX11 =+  mkXLibDeps { name = "libX11"+             , deps = [ prelude.unbounded "libxcb"+                      , prelude.unbounded "kbproto"+                      , prelude.unbounded "xextproto"+                      , prelude.unbounded "inputproto"+                      , prelude.unbounded "xtrans"+                      ]+             }+in++let inputproto =+  mkXProto "inputproto"+in++let xineramaproto =+  mkXProto "xineramaproto"+in++let xtrans =+  mkXLib "xtrans"+in++let libXrandr =+  mkXLibDeps { name = "libXrandr"+             , deps = [ prelude.unbounded "util-macros"+                      , prelude.unbounded "libXext"+                      , prelude.unbounded "libXrender"+                      , prelude.unbounded "libX11"+                      , prelude.unbounded "randrproto"+                      ]+             }+in++let libXinerama =+  mkXLibDeps { name = "libXinerama"+             , deps = [ prelude.unbounded "util-macros"+                      , prelude.unbounded "libX11"+                      , prelude.unbounded "libXext"+                      , prelude.unbounded "xineramaproto"+                      ]+             }+in++let libXext =+  mkXLibDeps { name = "libXext"+             , deps = [ prelude.lowerBound { name = "xextproto", lower = [7,1,99] }+                      , prelude.lowerBound { name = "xproto", lower = [7,0,13] }+                      , prelude.lowerBound { name = "libX11", lower = [1,6] }+                      ]+             }+in++let xextproto =+  mkXProto "xextproto"+in++let fixesproto =+  mkXProto "fixesproto"+in++let damageproto =+  mkXProto "damageproto"+in++let libXScrnSaver =+  λ(v : List Natural) →+    mkXLib "libXScrnSaver" v ⫽+      { pkgDeps = [ prelude.unbounded "util-macros"+                  , prelude.unbounded "libXext" -- >= 1.2+                  , prelude.unbounded "scrnsaverproto" -- >= 1.2+                  ]+      }+in++let bzip2 =+  let cc = prelude.mkCCArg+  in+  let bzipInstall =+    λ(cfg : types.BuildVars) →+      [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS+                                            , arguments = cc cfg # [ "PREFIX=${cfg.installDir}", "install", "-j${Natural/show cfg.cpus}" ]+                                            })+      ]+  in++  λ(v : List Natural) →+    prelude.simplePackage { name = "bzip2", version = v } ⫽+      { pkgUrl = "https://cytranet.dl.sourceforge.net/project/bzip2/bzip2-${prelude.showVersion v}.tar.gz"+      , configureCommand = prelude.doNothing+      , buildCommand = prelude.doNothing+      , installCommand = bzipInstall+      }+in++let expat =+  λ(v : List Natural) →+    prelude.simplePackage { name = "expat", version = v } ⫽+      { pkgUrl = "https://github.com/libexpat/libexpat/releases/download/R_${prelude.underscoreVersion v}/expat-${prelude.showVersion v}.tar.bz2" }+in++let gperf =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "gperf", version = v } ⫽+      { pkgUrl = "http://ftp.gnu.org/pub/gnu/gperf/gperf-${prelude.showVersion v}.tar.gz" }+in++let coreutils =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "coreutils", version = v } ⫽+      { installCommand = prelude.installWithBinaries [ "bin/install", "bin/chmod", "bin/rm", "bin/cp", "bin/ln", "bin/mkdir", "bin/test", "bin/od" ] }+in++let libsepol =+  let cc = prelude.mkCCArg+  in+  -- TODO: proper separation+  let sepolInstall =+    λ(cfg : types.BuildVars) →+      [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS+                                            , arguments = cc cfg # [ "PREFIX=${cfg.installDir}", "SHLIBDIR=${cfg.installDir}/lib", "CFLAGS=-Wno-error -O2", "install", "-j${Natural/show cfg.cpus}" ]+                                            , environment =+                                                Some (prelude.defaultPath cfg # [ prelude.mkLDFlags cfg.linkDirs, prelude.mkCFlags cfg.includeDirs, prelude.mkPkgConfigVar cfg.linkDirs ])+                                            })+      ]+  in++  λ(v : List Natural) →+    prelude.simplePackage { name = "libsepol", version = v } ⫽+      { pkgUrl = "https://github.com/SELinuxProject/selinux/releases/download/20180524/libsepol-${prelude.showVersion v}.tar.gz"+      , configureCommand = prelude.doNothing+      , buildCommand = prelude.doNothing+      , installCommand = sepolInstall+      , pkgBuildDeps = [ prelude.unbounded "flex" ]+      }+in++let libselinux =+  let cc = prelude.mkCCArg+  in+  -- TODO: proper separation+  let selinuxInstall =+    λ(cfg : types.BuildVars) →+      [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS+                                            , arguments = cc cfg+                                                # [ "PREFIX=${cfg.installDir}"+                                                  , "SHLIBDIR=${cfg.installDir}/lib"+                                                  , "EXTRA_CFLAGS=-Wno-error -lpcre " ++ (prelude.mkCFlags cfg.includeDirs).value+                                                  , "install"+                                                  , "-j${Natural/show cfg.cpus}"+                                                  ]+                                            , environment =+                                                Some (prelude.defaultPath cfg # [ prelude.mkLDFlags cfg.linkDirs+                                                                                , prelude.mkCFlags cfg.includeDirs+                                                                                , prelude.mkPkgConfigVar cfg.linkDirs+                                                                                , prelude.libPath cfg+                                                                                ])+                                            })+      ]+  in++  λ(v : List Natural) →+    prelude.simplePackage { name = "libselinux", version = v } ⫽+      { pkgUrl = "https://github.com/SELinuxProject/selinux/releases/download/20180524/libselinux-${prelude.showVersion v}.tar.gz"+      , configureCommand = prelude.doNothing+      , buildCommand = prelude.doNothing+      , installCommand = selinuxInstall+      , pkgDeps = [ prelude.unbounded "pcre"+                  , prelude.unbounded "libsepol"+                  ]+      }+in++let libXtst =+  mkXLibDeps { name = "libXtst"+             , deps = [ prelude.unbounded "libXi"+                      , prelude.unbounded "recordproto"+                      ]+             }+in++let libXi =+  mkXLibDeps { name = "libXi"+             , deps = [ prelude.unbounded "libXext" ]+             }+in++let mkGnomeNinja =+  λ(name : Text) →+  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in+    prelude.ninjaPackage { name = name, version = prelude.fullVersion x } ⫽+      { pkgUrl = "http://ftp.gnome.org/pub/gnome/sources/${name}/${versionString}/${name}-${fullVersion}.tar.xz" }+in++let at-spi-core =+  λ(x : { version : List Natural, patch : Natural }) →+    mkGnomeNinja "at-spi2-core" x ⫽+      { pkgDeps = [ prelude.unbounded "libXtst"+                  , prelude.unbounded "glib"+                  ]+      , installCommand =+          prelude.ninjaInstallWithPkgConfig [{ src = "build/atspi-2.pc", dest = "lib/pkgconfig/atspi-2.pc" }]+      }+in++let at-spi-atk =+  λ(x : { version : List Natural, patch : Natural }) →+    mkGnomeNinja "at-spi2-atk" x ⫽+      { pkgDeps = [ prelude.unbounded "at-spi2-core"+                  , prelude.lowerBound { name = "atk", lower = [2,29,2] }+                  , prelude.unbounded "libxml2"+                  ]+      , installCommand =+          prelude.ninjaInstallWithPkgConfig (prelude.mesonMoves [ "atk-bridge-2.0.pc" ])+      }+in++let libdrm =+  λ(v : List Natural) →+    prelude.ninjaPackage { name = "libdrm", version = v } ⫽+      { pkgUrl = "https://dri.freedesktop.org/libdrm/libdrm-${prelude.showVersion v}.tar.bz2"+      , pkgDeps = [ prelude.unbounded "libpciaccess"+                  , prelude.unbounded "cairo"+                  ]+      , installCommand =+          prelude.ninjaInstallWithPkgConfig (prelude.mesonMoves [ "libdrm.pc"+                                                                , "libdrm_amdgpu.pc"+                                                                , "libdrm_intel.pc"+                                                                , "libdrm_nouveau.pc"+                                                                , "libdrm_radeon.pc"+                                                                , "libkms.pc"+                                                                ])+      }+in++let libpciaccess =+  mkXLib "libpciaccess"+in++let markupSafe =+  λ(v : List Natural) →+    prelude.python3Package { name = "MarkupSafe", version = v } ⫽+      { pkgUrl = "https://files.pythonhosted.org/packages/source/M/MarkupSafe/MarkupSafe-${prelude.showVersion v}.tar.gz" }+in++let mako =+  λ(v : List Natural) →+    prelude.python3Package { name = "Mako", version = v } ⫽+      { pkgUrl = "https://files.pythonhosted.org/packages/source/M/Mako/Mako-${prelude.showVersion v}.tar.gz" }+in++let elfutils =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "elfutils", version = v } ⫽+      { pkgUrl = "https://sourceware.org/ftp/elfutils/${versionString}/elfutils-${versionString}.tar.bz2" }+in++let mkGnomeSimple =+  λ(name : Text) →+  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in+    prelude.simplePackage { name = name, version = prelude.fullVersion x } ⫽+      { pkgUrl = "http://ftp.gnome.org/pub/gnome/sources/${name}/${versionString}/${name}-${fullVersion}.tar.xz" }+in++let gtk3 =+  let gtkEnv =+    λ(cfg : types.BuildVars) →+      prelude.defaultPath cfg # [ { var = "LDFLAGS", value = (prelude.mkLDFlags cfg.linkDirs).value ++ " -lpcre -lfribidi" }+                                , prelude.mkCFlags cfg.includeDirs+                                , prelude.mkPkgConfigVar cfg.linkDirs+                                , prelude.libPath cfg+                                , prelude.mkLDRunPath cfg.linkDirs+                                , prelude.mkXdgDataDirs cfg.shareDirs+                                , prelude.mkLDPreload cfg.preloadLibs+                                ]+  in+  let gtkConfig =+    λ(cfg : types.BuildVars) →+      [ prelude.mkExe "configure"+      , prelude.call (prelude.defaultCall ⫽ { program = "./configure"+                                            , arguments = [ "--prefix=${cfg.installDir}" ]+                                            , environment = Some (gtkEnv cfg)+                                            })+      ]+  in++  λ(x : { version : List Natural, patch : Natural }) →+    mkGnomeSimple "gtk+" x ⫽+      { pkgName = "gtk3"+      , configureCommand = gtkConfig+      , buildCommand =+          λ(cfg : types.BuildVars) →+            prelude.buildWith (gtkEnv cfg) cfg+      , pkgDeps = [ prelude.lowerBound { name = "pango", lower = [1,41,0] }+                  , prelude.unbounded "at-spi2-atk"+                  , prelude.lowerBound { name = "atk", lower = [2,15,1] }+                  , prelude.lowerBound { name = "gdk-pixbuf", lower = [2,30,0] }+                  , prelude.unbounded "libXft"+                  , prelude.lowerBound { name = "libepoxy", lower = [1,4] }+                  ]+      }+in++let graphviz =+  λ(v : List Natural) →+    prelude.simplePackage { name = "graphviz", version = v } ⫽+      { pkgUrl = "https://graphviz.gitlab.io/pub/graphviz/stable/SOURCES/graphviz.tar.gz"+      , configureCommand = prelude.configureMkExes [ "iffe" ]+      , pkgDeps = [ prelude.unbounded "perl" ]+      , installCommand = prelude.installWithBinaries [ "bin/dot" ]+      }+in++let wayland =+  λ(v : List Natural) →+    prelude.simplePackage { name = "wayland", version = v } ⫽+      { pkgUrl = "https://wayland.freedesktop.org/releases/wayland-${prelude.showVersion v}.tar.xz"+      , pkgDeps = [ prelude.unbounded "libxml2" ]+      , configureCommand = prelude.configureWithFlags [ "--disable-documentation" ]+      }+in++let swig =+  λ(v : List Natural) →+    prelude.simplePackage { name = "swig", version = v } ⫽+      { pkgUrl = "https://downloads.sourceforge.net/swig/swig-${prelude.showVersion v}.tar.gz"+      , configureCommand = prelude.configureMkExes [ "Tools/config/install-sh" ]+      , installCommand = prelude.installWithBinaries [ "bin/swig" ]+      }+in++let lmdb =++  let cc = prelude.mkCCArg+  in++  let ar =+    λ(cfg : types.BuildVars) →+      Optional/fold types.TargetTriple cfg.targetTriple (List Text)+        (λ(tgt : types.TargetTriple) → ["AR=${prelude.printTargetTriple tgt}-ar"])+          ([] : List Text)+  in++  let lmdbInstall =+    λ(cfg : types.BuildVars) →+      [ prelude.call (prelude.defaultCall ⫽ { program = "make"+                                            , arguments = cc cfg # ar cfg # [ "prefix=${cfg.installDir}", "install", "-j${Natural/show cfg.cpus}" ]+                                            , procDir = Some "libraries/liblmdb" -- TODO: path on windows?+                                            })+      ]+  in++  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "lmdb", version = v } ⫽+      { pkgUrl = "https://github.com/LMDB/lmdb/archive/LMDB_${versionString}.tar.gz"+      , pkgSubdir = "lmdb-LMDB_${versionString}"+      , configureCommand = prelude.doNothing+      , buildCommand = prelude.doNothing+      , installCommand = lmdbInstall+      }+in++let gsl =+  λ(v : List Natural) →+    prelude.simplePackage { name = "gsl", version = v } ⫽+      { pkgUrl = "http://gnu.mirror.constant.com/gsl/gsl-${prelude.showVersion v}.tar.gz" }+in++let postgresql =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "postgresql", version = v } ⫽+      { pkgUrl = "https://ftp.postgresql.org/pub/source/v${versionString}/postgresql-${versionString}.tar.bz2"+      , configureCommand = prelude.configureWithFlags [ "--without-readline" ] -- TODO: set USE_DEV_URANDOM=1 or USE_WIN32_RANDOM=1 on windows+      }+in++let sqlite =+  λ(x : { year : Natural, version : List Natural }) →+    let versionString = prelude.squishVersion x.version in+    prelude.simplePackage { name = "sqlite", version = x.version } ⫽+      { pkgUrl = "https://sqlite.org/${Natural/show x.year}/sqlite-autoconf-${versionString}000.tar.gz"+      , pkgSubdir = "sqlite-autoconf-${versionString}000"+      }+in++let ragel =+  λ(v : List Natural) →+    prelude.simplePackage { name = "ragel", version = v } ⫽+      { pkgUrl = "http://www.colm.net/files/ragel/ragel-${prelude.showVersion v}.tar.gz"+      , installCommand = prelude.installWithBinaries [ "bin/ragel" ]+      }+in++let nano =+  λ(v : List Natural) →+    prelude.makeGnuExe { name = "nano", version = v } ⫽+      { pkgDeps = [ prelude.unbounded "ncurses" ] }+in++let libarchive =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libarchive", version = v } ⫽+      { pkgUrl = "https://www.libarchive.org/downloads/libarchive-${prelude.showVersion v}.tar.gz" }+in++let pygobject =+  λ(x : { version : List Natural, patch : Natural }) →+    mkGnomeSimple "pygobject" x ⫽+      { pkgDeps = [ prelude.unbounded "glib" ]+      , configureCommand = prelude.preloadCfg+      }+in++let pygtk =+  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in+    mkGnomeSimple "pygtk" x ⫽+      { pkgUrl = "http://ftp.gnome.org/pub/gnome/sources/pygtk/${versionString}/pygtk-${fullVersion}.tar.bz2"+      , configureCommand =+          λ(cfg : types.BuildVars) →+            prelude.mkExes [ "py-compile" ]+              # prelude.preloadCfg cfg+      , pkgDeps = [ prelude.lowerBound { name = "glib", lower = [2,8,0] }+                  , prelude.lowerBound { name = "pygobject", lower = [2,21,3] }+                  , prelude.unbounded "python2"+                  ]+      }+in++let libglade =+  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in+    prelude.simplePackage { name = "libglade", version = prelude.fullVersion x } ⫽+      { pkgUrl = "http://ftp.gnome.org/pub/gnome/sources/libglade/${versionString}/libglade-${fullVersion}.tar.bz2"+      , pkgDeps = [ prelude.lowerBound { name = "libxml2", lower = [2,4,10] }+                  , prelude.lowerBound { name = "gtk2", lower = [2,5,0] }+                  ]+      , configureCommand = prelude.configureLinkExtraLibs [ "fribidi" ]+      }+in++let scour =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.python3Package { name = "scour", version = v } ⫽+      { pkgUrl = "https://github.com/scour-project/scour/archive/v${versionString}/scour-${versionString}.tar.gz"+      , installCommand = prelude.installWithPy3Wrappers [ "scour" ]+      }+in++let libXpm =+  λ(v : List Natural) →+    mkXLib "libXpm" v ⫽+      { pkgDeps = [ prelude.unbounded "libXext"+                  , prelude.unbounded "libXt"+                  ]+      , pkgBuildDeps = [ prelude.unbounded "gettext" ]+      }+in++let libXt =+  mkXLibDeps { name = "libXt"+             , deps = [ prelude.unbounded "libICE"+                      , prelude.unbounded "libSM"+                      , prelude.unbounded "libX11"+                      , prelude.unbounded "kbproto"+                      ]+             }+in++let libICE =+  mkXLibDeps { name = "libICE"+             , deps = [ prelude.unbounded "xproto"+                      , prelude.unbounded "xtrans"+                      ]+             }+in++let libSM =+  mkXLibDeps { name = "libSM"+             , deps = [ prelude.unbounded "libICE"+                      , prelude.unbounded "util-linux"+                      ]+             }+in++let libXaw =+  mkXLibDeps { name = "libXaw"+             , deps = [ prelude.unbounded "libXmu"+                      , prelude.unbounded "libXpm"+                      ]+             }+in++let libXaw3d =+  mkXLibDeps { name = "libXaw3d"+             , deps = [ prelude.unbounded "libX11"+                      , prelude.unbounded "libXt"+                      , prelude.unbounded "libXmu"+                      , prelude.unbounded "libXext"+                      ]+             }+in++let libXmu =+  mkXLibDeps { name = "libXmu"+             , deps = [ prelude.unbounded "util-macros"+                      , prelude.unbounded "libXt"+                      , prelude.unbounded "libXext"+                      ]+             }+in++let libotf =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libotf", version = v } ⫽+      { pkgUrl = "http://download.savannah.gnu.org/releases/m17n/libotf-${prelude.showVersion v}.tar.gz"+      , pkgDeps = [ prelude.unbounded "freetype" ]+      }+in++let m17n =+  λ(v : List Natural) →+    prelude.simplePackage { name = "m17n-lib", version = v } ⫽+      { pkgUrl = "http://download.savannah.gnu.org/releases/m17n/m17n-lib-${prelude.showVersion v}.tar.gz"+      , buildCommand =+        λ(cfg : types.BuildVars) →+          [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS }) ]+      , pkgDeps = [ prelude.unbounded "libXt" ]+      }+in++let mkGimpPackage =+  λ(name : Text) →+  λ(x : { version : List Natural, patch : Natural }) →+    let versionString = prelude.showVersion x.version+    in+    let fullVersion = versionString ++ "." ++ Natural/show x.patch+    in+    prelude.simplePackage { name = name, version = prelude.fullVersion x } ⫽+      { pkgUrl = "https://download.gimp.org/pub/${name}/${versionString}/${name}-${fullVersion}.tar.bz2" }+in++let babl =+  mkGimpPackage "babl"+in++let gegl =+  λ(x : { version : List Natural, patch : Natural }) →+    mkGimpPackage "gegl" x ⫽+      { pkgDeps = [ prelude.lowerBound { name = "babl", lower = [0,1,58] }+                  , prelude.lowerBound { name = "glib", lower = [2,44,0] }+                  , prelude.unbounded "json-glib"+                  ]+      , configureCommand = prelude.preloadCfg+      }+in++let libexif =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "libexif", version = v } ⫽+      { pkgUrl = "https://nchc.dl.sourceforge.net/project/libexif/libexif/${versionString}/libexif-${versionString}.tar.bz2" }+in++let json-glib =+  λ(x : { version : List Natural, patch : Natural }) →+    mkGnomeNinja "json-glib" x ⫽+      { pkgDeps = [ prelude.unbounded "glib"+                  , prelude.unbounded "libjpeg-turbo"+                  , prelude.unbounded "libpng"+                  ]+      , installCommand =+          prelude.ninjaInstallWithPkgConfig (prelude.mesonMoves [ "json-glib-1.0.pc" ])+      }+in++let lcms2 =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "lcms2", version = v } ⫽+      { pkgUrl = "https://github.com/mm2/Little-CMS/archive/lcms${versionString}.tar.gz"+      , pkgSubdir = "Little-CMS-lcms${versionString}"+      }+in++let libtiff =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    -- TODO: use cmake + ninja build system if I ever figure out cross-compilation...+    prelude.simplePackage { name = "libtiff", version = v } ⫽+      { pkgUrl = "http://download.osgeo.org/libtiff/tiff-${versionString}.tar.gz"+      , pkgSubdir = "tiff-${versionString}"+      }+in++let libmypaint =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "libmypaint", version = v } ⫽+      { pkgUrl = "https://github.com/mypaint/libmypaint/releases/download/v${versionString}/libmypaint-${versionString}.tar.xz"+      , pkgDeps = [ prelude.unbounded "json-c" ]+      , pkgBuildDeps = [ prelude.unbounded "intltool" ]+      }+in++let json-c =+  λ(x : { version : List Natural, dateStr : Text }) →+    let versionString = "${prelude.showVersion x.version}-${x.dateStr}"+    in+    prelude.simplePackage { name = "json-c", version = x.version } ⫽+      { pkgUrl = "https://github.com/json-c/json-c/archive/json-c-${versionString}.tar.gz"+      , pkgSubdir = "json-c-json-c-${versionString}"+      }+in++let libopenjpeg =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "libopenjpeg", version = v } ⫽ prelude.cmakePackage ⫽+      { pkgUrl = "https://github.com/uclouvain/openjpeg/archive/v${versionString}.tar.gz"+      , pkgSubdir = "openjpeg-${versionString}"+      , installCommand =+          λ(cfg : types.BuildVars) →+            prelude.cmakeInstall cfg+              # [ prelude.symlink "lib/openjpeg-2.3/OpenJPEGConfig.cmake" "lib/OpenJPEGConfig.cmake" ]+      }+in++let libevent =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "libevent", version = v } ⫽+      { pkgUrl = "https://github.com/libevent/libevent/releases/download/release-${versionString}-stable/libevent-${versionString}-stable.tar.gz"+      , pkgSubdir = "libevent-${versionString}-stable"+      , pkgDeps = [ prelude.unbounded "openssl" ]+      }+in++let memcached =+  λ(v : List Natural) →+    prelude.simplePackage { name = "memcached", version = v } ⫽+      { pkgUrl = "https://memcached.org/files/memcached-${prelude.showVersion v}.tar.gz"+      , pkgDeps = [ prelude.unbounded "libevent" ]+      }+in++let motif =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "motif", version = v } ⫽+      { pkgUrl = "https://iweb.dl.sourceforge.net/project/motif/Motif%20${versionString}%20Source%20Code/motif-${versionString}.tar.gz"+      , pkgDeps = [ prelude.unbounded "libXft"+                  , prelude.unbounded "libpng"+                  , prelude.unbounded "freetype"+                  ]+      }+in++let libjpeg =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "libjpeg", version = v } ⫽+      { pkgUrl = "http://www.ijg.org/files/jpegsrc.v${versionString}c.tar.gz"+      , pkgSubdir = "jpeg-${versionString}c"+      }+in++let feh =+  let cc = prelude.mkCCArg+  let fehMake =+    λ(cfg : types.BuildVars) →+      { program = prelude.makeExe cfg.buildOS }+  let fehBuild =+    λ(v : List Natural) →+    λ(cfg : types.BuildVars) →+      [ prelude.call (prelude.defaultCall ⫽ fehMake cfg ⫽+                        { arguments = [ "feh.1" ]+                        , procDir = Some "man"+                        })+      , prelude.call (prelude.defaultCall ⫽ fehMake cfg ⫽+                        { arguments =+                            cc cfg #+                              [ "CFLAGS=${(prelude.mkCFlags cfg.includeDirs).value} -DPACKAGE=\\\"feh\\\" -DPREFIX=\\\"${cfg.installDir}\\\" -DVERSION=\\\"${prelude.showVersion v}\\\" ${(prelude.mkLDFlags cfg.linkDirs).value}"+                              , "feh"+                              ]+                        , procDir = Some "src"+                        })+      , prelude.call (prelude.defaultCall ⫽ fehMake cfg ⫽+                        { arguments = [ "feh.desktop" ]+                        , procDir = Some "share/applications"+                        })+      ]+  in+  let fehInstall =+    λ(cfg : types.BuildVars) →+      [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS+                                            , arguments = [ "CFLAGS=${(prelude.mkCFlags cfg.includeDirs).value}"+                                                          , "-j${Natural/show cfg.cpus}"+                                                          , "PREFIX=${cfg.installDir}"+                                                          , "install"+                                                          ]+                                            })+      , prelude.symlinkBinary "bin/feh"+      ]+  in++  λ(v : List Natural) →+    prelude.simplePackage { name = "feh", version = v } ⫽+      { pkgUrl = "https://github.com/derf/feh/archive/${prelude.showVersion v}.tar.gz"+      , configureCommand = prelude.doNothing+      , buildCommand = fehBuild v+      , installCommand = fehInstall+      , pkgBuildDeps = [ prelude.unbounded "sed" ]+      , pkgDeps = [ prelude.unbounded "imlib2"+                  , prelude.unbounded "libXt"+                  , prelude.unbounded "libXinerama"+                  , prelude.unbounded "curl"+                  ]+      }+in++let imlib2 =+  λ(v : List Natural) →+    prelude.simplePackage { name = "imlib2", version = v } ⫽+      { pkgUrl = "https://downloads.sourceforge.net/enlightenment/imlib2-${prelude.showVersion v}.tar.bz2"+      , pkgDeps = [ prelude.unbounded "libXext"+                  , prelude.unbounded "freetype"+                  ]+      }+in++let libicu =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libicu", version = v } ⫽+      { pkgUrl = "http://download.icu-project.org/files/icu4c/${prelude.showVersion v}/icu4c-${prelude.underscoreVersion v}-src.tgz"+      , pkgSubdir = "icu/source"+      }+in++let jemalloc =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "jemalloc", version = v } ⫽+      { pkgUrl = "https://github.com/jemalloc/jemalloc/releases/download/${versionString}/jemalloc-${versionString}.tar.bz2"+      , configureCommand = prelude.configureMkExes [ "include/jemalloc/internal/private_symbols.sh"+                                                   , "include/jemalloc/internal/public_namespace.sh"+                                                   , "include/jemalloc/internal/public_unnamespace.sh"+                                                   , "include/jemalloc/jemalloc_rename.sh"+                                                   , "include/jemalloc/jemalloc_mangle.sh"+                                                   , "include/jemalloc/jemalloc.sh"+                                                   ]+      }+in++let gperftools =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "gperftools", version = v } ⫽+      { pkgUrl = "https://github.com/gperftools/gperftools/releases/download/gperftools-${versionString}/gperftools-${versionString}.tar.gz" }+in++let openssh =+  let opensshInstall =+    λ(cfg : types.BuildVars) →+      [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS+                                            , arguments =+                                                [ "PRIVSEP_PATH=${cfg.installDir}/var"+                                                , "install"+                                                , "-j${Natural/show cfg.cpus}"+                                                ]+                                            , environment =+                                                Some (prelude.defaultPath cfg # [ prelude.mkPkgConfigVar cfg.linkDirs+                                                                                , prelude.libPath cfg+                                                                                ])+                                            })+      ]+  in+  λ(v : List Natural) →+    prelude.simplePackage { name = "openssh", version = v } ⫽+      { pkgUrl = "https://mirrors.gigenet.com/pub/OpenBSD/OpenSSH/portable/openssh-${prelude.showVersion v}p1.tar.gz"+      , pkgSubdir = "openssh-${prelude.showVersion v}p1"+      , installCommand = opensshInstall+      , pkgDeps = [ prelude.unbounded "openssl" ]+      }+in++let libxslt =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libxslt", version = v } ⫽+      { pkgUrl = "http://xmlsoft.org/sources/libxslt-${prelude.showVersion v}.tar.gz"+      , pkgDeps = [ prelude.unbounded "libxml2" ]+      }+in++let libepoxy =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.ninjaPackage { name = "libepoxy", version = v } ⫽+      { pkgUrl = "https://github.com/anholt/libepoxy/releases/download/${versionString}/libepoxy-${versionString}.tar.xz"+      , pkgDeps = [ prelude.unbounded "mesa" ]+      , installCommand =+          prelude.ninjaInstallWithPkgConfig (prelude.mesonMoves [ "epoxy.pc" ])+      }+in++let mesa =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "mesa", version = v } ⫽+      { pkgUrl = "https://mesa.freedesktop.org/archive/mesa-${prelude.showVersion v}.tar.xz"+      , pkgDeps = [ prelude.lowerBound { name = "libdrm", lower = [2,4,75] }+                  , prelude.unbounded "libXdamage"+                  , prelude.unbounded "libXfixes"+                  , prelude.unbounded "libXxf86vm"+                  , prelude.lowerBound { name = "libxshmfence", lower = [1,1] }+                  , prelude.lowerBound { name = "glproto", lower = [1,4,14] }+                  , prelude.lowerBound { name = "dri2proto", lower = [2,8] }+                  , prelude.unbounded "libXrandr"+                  ]+      , configureCommand = prelude.configureWithFlags [ "--with-gallium-drivers=nouveau,swrast" ] -- disable radeon drivers so we don't need LLVM+      }+in++let libXdamage =+  mkXLibDeps { name = "libXdamage"+             , deps = [ prelude.unbounded "libXfixes"+                      , prelude.unbounded "damageproto"+                      ]+             }+in++let libXfixes =+  mkXLibDeps { name = "libXfixes"+             , deps = [ prelude.unbounded "xproto"+                      , prelude.unbounded "fixesproto"+                      , prelude.unbounded "xextproto"+                      , prelude.unbounded "libX11"+                      ]+             }+in++let libXxf86vm =+  mkXLibDeps { name = "libXxf86vm"+             , deps = [ prelude.unbounded "xproto"+                      , prelude.unbounded "libX11"+                      , prelude.unbounded "xextproto"+                      , prelude.unbounded "libXext"+                      , prelude.unbounded "xf86vidmodeproto"+                      ]+             }+in++let libxshmfence =+  mkXLibDeps { name = "libxshmfence", deps = [ prelude.unbounded "xproto" ] }+in++let gnome-doc-utils =+  λ(x : { version : List Natural, patch : Natural }) →+    mkGnomeSimple "gnome-doc-utils" x ⫽+      { pkgDeps = [ prelude.lowerBound { name = "libxslt", lower = [1,1,8] }+                  , prelude.lowerBound { name = "libxml2", lower = [2,6,12] }+                  ]+      , pkgBuildDeps = [ prelude.lowerBound { name = "intltool", lower = [0,35,0] } ]+      , configureCommand = prelude.configureMkExes [ "py-compile" ]+      }+in++let itstool =+  λ(v : List Natural) →+    prelude.simplePackage { name = "itstool", version = v } ⫽+      { pkgUrl = "http://files.itstool.org/itstool/itstool-${prelude.showVersion v}.tar.bz2"+      , pkgDeps = [ prelude.unbounded "libxml2" ]+      }+in++let gexiv2 =+  λ(x : { version : List Natural, patch : Natural }) →+    mkGnomeNinja "gexiv2" x ⫽+      { pkgDeps = [ prelude.unbounded "exiv2"+                  , prelude.unbounded "glib"+                  ]+      , installCommand =+          prelude.ninjaInstallWithPkgConfig (prelude.mesonMoves [ "gexiv2.pc" ])+      }+in++let exiv2 =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.simplePackage { name = "exiv2", version = v } ⫽ prelude.cmakePackage ⫽+      { pkgUrl = "http://www.exiv2.org/builds/exiv2-${versionString}-Source.tar.gz"+      , pkgSubdir = "exiv2-${versionString}-Source"+      }+in++let libtiff =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v in+    prelude.ninjaPackage { name = "libtiff", version = v } ⫽+      { pkgUrl = "https://download.osgeo.org/libtiff/tiff-${versionString}.tar.gz"+      , pkgSubdir = "tiff-${versionString}"+      , configureCommand = prelude.cmakeConfigureNinja+      }+in++let nspr =+  λ(v : List Natural) →+    let versionString = prelude.showVersion v+    in+    let bitFlag =+      λ(cfg : types.BuildVars) →+        if prelude.isX64 (prelude.archCfg cfg)+          then [ "--enable-64bit" ]+          else ([] : List Text)+    in++    prelude.simplePackage { name = "nspr", version = v } ⫽+      { pkgUrl = "https://archive.mozilla.org/pub/nspr/releases/v${versionString}/src/nspr-${versionString}.tar.gz"+      , pkgSubdir = "nspr-${versionString}/nspr"+      , configureCommand =+          λ(cfg : types.BuildVars) →+            prelude.configureWithFlags (bitFlag cfg) cfg+      }+in++let libthai =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libthai", version = v } ⫽+      { pkgUrl = "https://linux.thai.net/pub/thailinux/software/libthai/libthai-${prelude.showVersion v}.tar.xz"+      , pkgDeps = [ prelude.unbounded "libdatrie" ]+      }+in++let libdatrie =+  λ(v : List Natural) →+    prelude.simplePackage { name = "libdatrie", version = v } ⫽+      { pkgUrl = "https://linux.thai.net/pub/thailinux/software/libthai/libdatrie-${prelude.showVersion v}.tar.xz" }+in++let joe =+  λ(v : List Natural) →+    prelude.simplePackage { name = "joe", version = v } ⫽+      { pkgUrl = "https://downloads.sourceforge.net/joe-editor/joe-${prelude.showVersion v}.tar.gz"+      , installCommand = prelude.installWithBinaries [ "bin/joe" ]+      }+in++[ autoconf [2,69]+, automake [1,16,1]+, at-spi-atk { version = [2,30], patch = 0 }+, at-spi-core { version = [2,30], patch = 0 }+, atk { version = [2,30], patch = 0 }+, babl { version = [0,1], patch = 60 }+, binutils [2,31]+, bison [3,3]+, bzip2 [1,0,6]+, cairo [1,16,0]+, chickenScheme [5,0,0]+, cmake { version = [3,13], patch = 2 }+, coreutils [8,30]+, curl [7,63,0]+, damageproto [1,2,1]+, dbus [1,12,10]+, dri2proto [2,8]+, elfutils [0,175]+, emacs [26,1]+, exiv2 [0,27,0]+, expat [2,2,6]+, feh [3,1,1]+, fixesproto [5,0]+, fontconfig [2,13,1]+, flex [2,6,3]+, fltk { version = [1,3,4], patch = 2 }+, freetype-prebuild [2,9,1] -- TODO: force both to have same version?+, freetype [2,9,1]+, fribidi [1,0,5]+, gawk [4,2,1]+, gc [8,0,2]+, gdb [8,2]+, gdk-pixbuf { version = [2,38], patch = 0 }+, gegl { version = [0,4], patch = 12 }+, gettext [0,19,8]+, gexiv2 { version = [0,11], patch = 0 }+, gperf [3,1]+, gperftools [2,7]+, giflib [5,1,4]+, git [2,19,2]+, glib { version = [2,58], patch = 3 } -- TODO: bump to 2.59.0 once gobject-introspection supports it+, glproto [1,4,17]+, json-glib { version = [1,4], patch = 4 }+, glibc [2,28]+, gmp [6,1,2]+, gobject-introspection { version = [1,59], patch = 3 }+, gnome-doc-utils { version = [0,20], patch = 10 }+, gnupg [2,2,12]+, gnutls { version = [3,6], patch = 5 }+, graphviz [2,40,1]+, gsl [2,5]+, gtk2 { version = [2,24], patch = 32 }+, gtk3 { version = [3,24], patch = 4 }+, gzip [1,9]+, harfbuzz [2,3,0]+, imageMagick [7,0,8]+, imlib2 [1,5,1]+, inputproto [2,3,2]+, intltool [0,51,0]+, itstool [2,0,5]+, jemalloc [5,1,0]+, jpegTurbo [2,0,1]+, joe [4,6]+, json-c { version = [0,13,1], dateStr = "20180305" }+, kbproto [1,0,7]+, lapack [3,8,0]+, lcms2 [2,9]+, libarchive [3,3,3]+, libassuan [2,5,2]+, libatomic_ops [7,6,8]+, libdatrie [0,2,12]+, libdrm [2,4,96]+, libepoxy [1,5,3]+, libevent [2,1,8]+, libexif [0,6,21]+, libffi [3,2,1]+, libgcrypt [1,8,4]+, libglade { version = [2,6], patch = 4 }+, libgpgError [1,33]+, libICE [1,0,9]+, libicu [63,1]+, libjpeg [9]+, libksba [1,3,5]+, libmypaint [1,3,0]+, libnettle [3,4,1]+, libpciaccess [0,14]+, libpng [1,6,35]+, libpthread-stubs [0,4]+, libopenjpeg [2,3,0]+, libotf [0,9,16]+, libselinux [2,8]+, libsepol [2,8]+, libssh2 [1,8,0]+, libtasn1 [4,13]+, libtiff [4,0,10]+, libtool [2,4,6]+, libuv [1,24,0]+, libSM [1,2,3]+, libthai [0,1,28]+, libtiff [4,0,10]+, libX11 [1,6,7]+, libXau [1,0,8]+, libXaw [1,0,13]+, libXaw3d [1,6,3]+, libxcb [1,13]+, libXdamage [1,1,4]+, libXdmcp [1,1,2]+, libXext [1,3,3]+, libXfixes [5,0,3]+, libXft [2,3,2]+, libXi [1,7]+, libXinerama [1,1,4]+, libxml2 [2,9,8]+, libXmu [1,1,2]+, libXpm [3,5,12]+, libXScrnSaver [1,2,3]+, libxshmfence [1,3]+, libxslt [1,1,33]+, libXrandr [1,5,1]+, libXrender [0,9,10]+, libXt [1,1,5]+, libXtst [1,2,3]+, libXxf86vm [1,1,4]+, lmdb [0,9,23]+, lua [5,3,5]+, m17n [1,8,0]+, m4 [1,4,18]+, mako [1,0,7]+, markupSafe [1,0]+, memcached [1,5,12]+, mesa [18,3,1]+, meson [0,49,0]+, motif [2,3,8]+, musl [1,1,20]+, nano [3,2]+, nasm [2,14]+, ncurses [6,1]+, nginx [1,15,7]+, ninja [1,8,2]+, npth [1,6]+, nspr [4,20]+, openssh [7,9]+, openssl [1,1,1]+, p11kit [0,23,15]+, pango { version = [1,43], patch = 0 }+, pcre [8,42]+, pcre2 [10,32]+, perl5 [5,28,1]+, pixman [0,36,0]+, pkg-config [0,29,2]+, postgresql [11,1]+, pycairo [1,18,0]+, pygobject { version = [2,28], patch = 7 }+, pygtk { version = [2,24], patch = 0 }+, python [2,7,15]+, python [3,7,2]+, qrencode [4,0,2]+, ragel [6,10]+, randrproto [1,5,0]+, re2c [1,1,1]+, readline [7,0]+, recordproto [1,14,2]+, renderproto [0,11,1]+, scour [0,37]+, scrnsaverproto [1,2,2]+, sdl2 [2,0,9]+, sed [4,5]+, shared-mime-info [1,10]+, sqlite { year = 2018, version = [3,26,0] }+, swig [3,0,12]+, tar [1,30]+, unistring [0,9,10]+, util-linux [2,33]+, util-macros [1,19,2]+, valgrind [3,14,0]+, vim [8,1]+, wayland [1,16,0]+, wget [1,20]+, which [2,21]+, xcb-proto [1,13]+, xextproto [7,3,0]+, xf86vidmodeproto [2,3,1]+, xineramaproto [1,2]+, xmlParser [2,44]+, xproto [7,0,31]+, xtrans [1,3,5]+, xz [5,2,4]+, zlib [1,2,11]+]
+ src/CPkgPrelude.hs view
@@ -0,0 +1,52 @@+module CPkgPrelude ( -- * Base reëxports+                     Generic+                   , Natural+                   , void+                   , when+                   , unless+                   , traverse_+                   , fold+                   , toList+                   , filterM+                   , ($>)+                   , (<=<)+                   , MonadIO (..)+                   , Void+                   -- * Dhall reëxports+                   , Inject+                   , Interpret+                   -- * hashable reëxports+                   , Hashable+                   -- * Exports from "Control.Composition"+                   , (.**)+                   -- * Exports from "Data.Binary"+                   , Binary+                   -- prettyprinter reëxports+                   , Doc+                   , Pretty (..)+                   , punctuate+                   -- * microlens reëxports+                   , Lens'+                   , over+                   -- * Exports from "System.FilePath"+                   , (</>)+                   -- * Exports from "System.Directory"+                   , doesFileExist+                   , getAppUserDataDirectory+                   ) where++import           Control.Composition       ((.**))+import           Control.Monad+import           Control.Monad.IO.Class    (MonadIO (..))+import           Data.Binary               (Binary)+import           Data.Foldable+import           Data.Functor              (($>))+import           Data.Hashable             (Hashable)+import           Data.Text.Prettyprint.Doc+import           Data.Void                 (Void)+import           Dhall                     (Inject, Interpret)+import           GHC.Generics              (Generic)+import           GHC.Natural               (Natural)+import           Lens.Micro                (Lens', over)+import           System.Directory+import           System.FilePath           ((</>))
+ src/Data/Text/Prettyprint/Doc/Custom.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE OverloadedStrings #-}++module Data.Text.Prettyprint.Doc.Custom ( (<#>)+                                        , (<##>)+                                        , vdisplay+                                        , dashed+                                        ) where++import           Data.Foldable             (foldl')+import           Data.Text.Prettyprint.Doc++infixr 5 <#>+infixr 5 <##>++(<#>) :: Doc a -> Doc a -> Doc a+(<#>) a b = a <> line <> b++(<##>) :: Doc a -> Doc a -> Doc a+(<##>) a b = a <> hardline <> b++vdisplay :: [Doc a] -> Doc a+vdisplay = foldl' (<#>) mempty++dashed :: [Doc a] -> Doc a+dashed = concatWith (\x y -> x <> "-" <> y)
+ src/Package/C.hs view
@@ -0,0 +1,51 @@+module Package.C (+                 -- * Types+                   CPkg (..)+                 , BuildVars (..)+                 , Version (..)+                 , Verbosity (..)+                 , TargetTriple (..)+                 , Command (..)+                 , OS (..)+                 , Arch (..)+                 , Manufacturer (..)+                 , ABI (..)+                 , InstallDb (..)+                 , BuildCfg (..)+                 , MonadDb+                 , PkgM+                 , Platform+                 -- * Functions+                 , buildCPkg+                 , runPkgM+                 , globalPkgDir+                 , printLinkerFlags+                 , printCompilerFlags+                 , printPkgConfigPath+                 , printIncludePath+                 , printLibPath+                 , printCabalFlags+                 , buildByName+                 -- * Dhall functionality+                 , cPkgDhallToCPkg+                 , getCPkg+                 , getPkgs+                 -- * Packaging+                 , displayPackageSet+                 , allPackages+                 -- * Parsers+                 , parseTriple+                 , parseTripleIO+                 , parseHostIO+                 ) where++import           Package.C.Build+import           Package.C.Build.Tree+import           Package.C.Db.Monad+import           Package.C.Db.Register+import           Package.C.Db.Type+import           Package.C.Dhall+import           Package.C.Monad+import           Package.C.PackageSet+import           Package.C.Triple+import           Package.C.Type
+ src/Package/C/Build.hs view
@@ -0,0 +1,177 @@+module Package.C.Build ( buildCPkg+                       , getVars+                       , cPkgToDir+                       ) where++import           Control.Concurrent          (getNumCapabilities)+import           CPkgPrelude+import           Data.Maybe                  (isJust)+import qualified Data.Text.IO                as TIO+import           Package.C.Build.OS+import           Package.C.Db.Register+import           Package.C.Fetch+import           Package.C.Logging+import           Package.C.Monad+import           Package.C.Type+import           System.Directory+import           System.Directory.Executable (mkExecutable)+import           System.FilePath             (takeDirectory, takeFileName, (</>))+import           System.FilePath.Glob+import           System.IO.Temp              (withSystemTempDirectory)+import           System.Process+import           System.Process.Ext++envVarSplit :: EnvVar -> (String, String)+envVarSplit (EnvVar ev x) = (ev, x)++stepToProc :: FilePath -- ^ Package build directory+           -> FilePath -- ^ Package install directory+           -> Command+           -> PkgM ()+stepToProc fp _ (Call p as envs dir') = do+    let dir'' = maybe fp (fp </>) dir'+        envVars = fmap envVarSplit <$> envs+    putDiagnostic ("Running " ++ p ++ " with arguments " ++ unwords as ++ " in directory " ++ dir'' ++ " with environment " ++ show envVars)+    waitProcess $ (proc p as) { cwd = Just dir'', std_in = CreatePipe, env = envVars }+stepToProc dir' _ (MakeExecutable fp) = do+    putDiagnostic ("Marking " ++ (dir' </> fp) ++ " as executable...")+    liftIO $ mkExecutable (dir' </> fp)+stepToProc dir' _ (CreateDirectory d) = do+    putDiagnostic ("Creating directory " ++ (dir' </> d) ++ "...")+    liftIO $ createDirectoryIfMissing True (dir' </> d)+stepToProc _ p (SymlinkBinary file') = do+    binDir <- (</> "bin") <$> globalPkgDir+    let actualBin = p </> file'+    liftIO $ createDirectoryIfMissing True binDir+    liftIO $ createFileLink actualBin (binDir </> takeFileName file')+stepToProc _ p (Symlink tgt' lnk) = do+    let linkAbs = p </> lnk+    putDiagnostic ("Creating directory" ++ takeDirectory linkAbs ++ "...")+    liftIO $ createDirectoryIfMissing True (takeDirectory linkAbs)+    -- TODO: diagnostics for symlinks+    liftIO $ createFileLink (p </> tgt') linkAbs+stepToProc dir' _ (Write out fp) =+    liftIO (TIO.writeFile (dir' </> fp) out)+stepToProc dir' p (CopyFile src' dest') = do+    let absSrc = dir' </> src'+        absDest = p </> dest'+    putDiagnostic ("Copying file " ++ absSrc ++ " to " ++ absDest ++ "...")+    liftIO $ createDirectoryIfMissing True (takeDirectory absDest)+    liftIO $ copyFileWithMetadata absSrc absDest++processSteps :: (Traversable t)+             => FilePath -- ^ Build directory+             -> FilePath -- ^ Install directory+             -> t Command+             -> PkgM ()+processSteps pkgDir instDir = traverse_ (stepToProc pkgDir instDir)++configureInDir :: CPkg+               -> BuildVars+               -> FilePath -- ^ Build directory+               -> PkgM ()+configureInDir cpkg cfg p =++    let steps = configureCommand cpkg cfg+    in+        putNormal ("Configuring " ++ pkgName cpkg) *>+        processSteps p (installDir cfg) steps++buildInDir :: CPkg+           -> BuildVars+           -> FilePath -- ^ Build directory+           -> FilePath -- ^ Install directory+           -> PkgM ()+buildInDir cpkg cfg p p' = do+    putNormal ("Building " ++ pkgName cpkg)+    processSteps p p' (buildCommand cpkg cfg)++installInDir :: CPkg+             -> BuildVars+             -> FilePath -- ^ Build directory+             -> FilePath -- ^ Install directory+             -> PkgM ()+installInDir cpkg cfg p p' =+    putNormal ("Installing " ++ pkgName cpkg) *>+    processSteps p p' (installCommand cpkg cfg)++fetchCPkg :: CPkg+          -> FilePath -- ^ Directory for intermediate build files+          -> PkgM ()+fetchCPkg cpkg = fetchUrl (pkgUrl cpkg) (pkgName cpkg)++buildCPkg :: CPkg+          -> Maybe TargetTriple+          -> Bool -- ^ Should we build static libraries?+          -> [FilePath] -- ^ Shared data directories+          -> [FilePath] -- ^ Library directories+          -> [FilePath] -- ^ Include directories+          -> [FilePath] -- ^ Directories to add to @PATH@+          -> PkgM ()+buildCPkg cpkg host sta shr libs incls bins = do++    buildVars <- getVars host sta shr libs incls bins++    -- TODO: use a real database+    installed <- packageInstalled cpkg host buildVars++    when installed $+        putDiagnostic ("Package " ++ pkgName cpkg ++ " already installed, skipping.")++    unless installed $+        forceBuildCPkg cpkg host buildVars++getPreloads :: [ FilePath ] -> IO [ FilePath ]+getPreloads =+    fmap fold . traverse (\fp -> namesMatching (fp </> "*.so"))++-- only really suitable for hashing at this point, since we use @""@ as the+-- install directory. we use this to get a hash which we then use to get the+-- *real* install directory, which we then use with @configureVars@ to set+-- things up correctly - otherwise we would have a circularity+getVars :: Maybe TargetTriple+        -> Bool -- ^ Should we build static libraries?+        -> [FilePath] -- ^ Shared data directories+        -> [FilePath] -- ^ Library directories+        -> [FilePath] -- ^ Include directories+        -> [FilePath] -- ^ Directories to add to @PATH@+        -> PkgM BuildVars+getVars host sta shr links incls bins = do+    nproc <- liftIO getNumCapabilities+    pure (BuildVars "" "" host (isJust host) incls [] shr links bins dhallOS dhallArch sta nproc)+    -- we don't run getPreloads until later because that might be slow++-- diagnosticDirectory :: String -> (FilePath -> m a) -> m a+-- diagnosticDirectory s f = f (s ++ "-diagnostic")++-- TODO: more complicated solver, garbage collector, and all that.+-- Basically nix-style builds for C libraries+forceBuildCPkg :: CPkg+               -> Maybe TargetTriple+               -> BuildVars+               -> PkgM ()+forceBuildCPkg cpkg host buildVars = do++    pkgDir <- cPkgToDir cpkg host buildVars++    liftIO $ createDirectoryIfMissing True pkgDir++    withSystemTempDirectory "cpkg" $ \p -> do++        putDiagnostic ("Setting up temporary directory in " ++ p)++        fetchCPkg cpkg p++        let p' = p </> pkgSubdir cpkg++        lds <- liftIO $ getPreloads $ linkDirs buildVars++        let buildConfigured = buildVars { installDir = pkgDir, currentDir = p, preloadLibs = lds }++        configureInDir cpkg buildConfigured p'++        buildInDir cpkg buildConfigured p' pkgDir++        installInDir cpkg buildConfigured p' pkgDir++        registerPkg cpkg host buildVars -- not configured
+ src/Package/C/Build/OS.hs view
@@ -0,0 +1,26 @@+module Package.C.Build.OS ( dhallOS+                          , dhallArch+                          ) where++import           Package.C.Triple.Type      hiding (arch, os)+import           Package.C.Type.Shared+import           System.Info           (arch, os)++dhallArch :: Arch+dhallArch = case arch of+    "x86_64" -> X64+    "x86"    -> X86+    "arm"    -> Arm+    _        -> error "unrecognized architecture"++dhallOS :: OS+dhallOS = case os of+    "freebsd"   -> FreeBSD+    "openbsd"   -> OpenBSD+    "netbsd"    -> NetBSD+    "solaris"   -> Solaris+    "dragonfly" -> Dragonfly+    "linux"     -> Linux+    "darwin"    -> Darwin+    "mingw32"   -> Windows+    _           -> error "unrecognized OS"
+ src/Package/C/Build/Tree.hs view
@@ -0,0 +1,96 @@+module Package.C.Build.Tree ( buildByName+                            ) where++import           Control.Recursion+import           CPkgPrelude+import           Data.Containers.ListUtils (nubOrd)+import           Data.List                 (isInfixOf)+import           Package.C.Build+import           Package.C.Monad+import           Package.C.PackageSet+import           Package.C.Type+import           Package.C.Type.Tree+import           System.Directory          (doesDirectoryExist)+import           System.FilePath           ((</>))++data BuildDirs = BuildDirs { libraries :: [FilePath]+                           , share     :: [FilePath]+                           , include   :: [FilePath]+                           , binaries  :: [FilePath]+                           }++getAll :: [BuildDirs] -> BuildDirs+getAll bds =+    let go f = fold (f <$> bds)+    in BuildDirs (go libraries) (go share) (go include) (go binaries)++-- in order to prevent the "vanilla" libffi from preceding the *cross* libffi,+-- we filter out any directory that doesn't contain the target triple. this+-- causes further bugs and it's slow+--+-- Really we should allow *all* libdirs for Python/Perl here, since they won't+-- (hopefully) pollute the pkg-config path...+immoralFilter :: Maybe TargetTriple -> [FilePath] -> [FilePath]+immoralFilter Nothing fps = fps+immoralFilter (Just tgt') fps =+    let infixDir = show tgt'+    in filter (\fp -> infixDir `isInfixOf` fp || "meson" `isInfixOf` fp || "XML-Parser" `isInfixOf` fp || "python3" `isInfixOf` fp) fps -- FIXME: more principled approach++buildWithContext :: DepTree CPkg+                 -> Maybe TargetTriple+                 -> Bool -- ^ Should we build static libraries?+                 -> PkgM ()+buildWithContext cTree host sta = zygoM' dirAlg buildAlg cTree++    where buildAlg :: DepTreeF CPkg (BuildDirs, ()) -> PkgM ()+          buildAlg (DepNodeF c preBds) =+            buildCPkg c host sta ds (immoralFilter host ls) is bs+                where (BuildDirs ls ds is bs) = getAll (fst <$> preBds)+          buildAlg (BldDepNodeF c preBds) =+            buildCPkg c Nothing False ds ls is bs -- don't use static libraries for build dependencies+                where (BuildDirs ls ds is bs) = getAll (fst <$> preBds)++          mkBuildDirs :: MonadIO m => FilePath -> BuildDirs -> m BuildDirs+          mkBuildDirs pkgDir (BuildDirs ls ds is bs) = do+            let linkDir = pkgDir </> "lib"+                linkDir64 = pkgDir </> "lib64"+                includeDir = pkgDir </> "include"+                dataDir = pkgDir </> "share"+                binDir = pkgDir </> "bin"+                links = linkDir64 : linkDir : ls+                bins = binDir : bs+                shares = dataDir : ds++            includeExists <- liftIO (doesDirectoryExist includeDir)+            let includes = if includeExists+                then includeDir : is+                else is++            pure (BuildDirs (nubOrd links) (nubOrd shares) (nubOrd includes) (nubOrd bins))++          dirAlg :: DepTreeF CPkg BuildDirs -> PkgM BuildDirs+          dirAlg (DepNodeF c bds) = do++            let bldDirs@(BuildDirs ls ds is bs) = getAll bds++            buildVars <- getVars host sta ds (immoralFilter host ls) is bs++            pkgDir <- cPkgToDir c host buildVars++            mkBuildDirs pkgDir bldDirs++          dirAlg (BldDepNodeF c bds) = do++            let bldDirs@(BuildDirs ls ds is bs) = getAll bds++            buildVars <- getVars Nothing False ds ls is bs++            pkgDir <- cPkgToDir c Nothing buildVars++            mkBuildDirs pkgDir bldDirs++-- TODO: should this parse a string into a TargetTriple instead?+buildByName :: PackId -> Maybe TargetTriple -> Maybe String -> Bool -> PkgM ()+buildByName pkId host pkSet sta = do+    allPkgs <- liftIO (pkgsM pkId pkSet)+    buildWithContext allPkgs host sta
+ src/Package/C/Db/Memory.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE FlexibleContexts #-}++module Package.C.Db.Memory ( strictIndex+                           , pkgIndex+                           , globalPkgDir+                           , memIndex+                           ) where++import           Control.Monad.State.Class+import           CPkgPrelude+import           Data.Binary               (decode)+import qualified Data.ByteString           as BS+import qualified Data.ByteString.Lazy      as BSL+import           Package.C.Db.Monad+import           Package.C.Db.Type++pkgIndex :: MonadIO m => m FilePath+pkgIndex = (</> "index.bin") <$> globalPkgDir++globalPkgDir :: MonadIO m => m FilePath+globalPkgDir = liftIO (getAppUserDataDirectory "cpkg")++memIndex :: MonadDb m => m InstallDb+memIndex = get++strictIndex :: MonadIO m => m InstallDb+strictIndex = do++    indexFile <- pkgIndex+    -- Add some proper error handling here+    existsIndex <- liftIO (doesFileExist indexFile)++    if existsIndex+        then decode . BSL.fromStrict <$> liftIO (BS.readFile indexFile)+        else pure mempty
+ src/Package/C/Db/Monad.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE ConstraintKinds #-}++module Package.C.Db.Monad ( MonadDb+                          ) where++import           Control.Monad.State+import           Package.C.Db.Type++type MonadDb = MonadState InstallDb
+ src/Package/C/Db/Register.hs view
@@ -0,0 +1,173 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes       #-}++-- TODO: a lot of the stuff in this module could be made pure so that it only+-- gets called once+module Package.C.Db.Register ( registerPkg+                             , cPkgToDir+                             , globalPkgDir+                             , printCompilerFlags+                             , printLinkerFlags+                             , printPkgConfigPath+                             , printIncludePath+                             , printLibPath+                             , printCabalFlags+                             , packageInstalled+                             , allPackages+                             , parseHostIO+                             , Platform+                             ) where++import           Control.Monad.Reader+import           Control.Monad.State  (modify)+import           CPkgPrelude+import           Data.Binary          (encode)+import qualified Data.ByteString.Lazy as BSL+import           Data.Hashable        (Hashable (..))+import qualified Data.Set             as S+import           Numeric              (showHex)+import           Package.C.Db.Memory+import           Package.C.Db.Monad+import           Package.C.Db.Type+import           Package.C.Error+import           Package.C.Logging+import           Package.C.Triple+import           Package.C.Type       hiding (Dep (name))++type Platform = String+type FlagPrint = forall m. MonadIO m => BuildCfg -> m String++allPackages :: IO [String]+allPackages = do+    (InstallDb index) <- strictIndex+    pure (buildName <$> toList index)++printCompilerFlags :: (MonadIO m, MonadDb m) => String -> Maybe Platform -> m ()+printCompilerFlags = printFlagsWith buildCfgToCFlags++printLinkerFlags :: (MonadIO m, MonadDb m) => String -> Maybe Platform -> m ()+printLinkerFlags = printFlagsWith buildCfgToLinkerFlags++printPkgConfigPath :: (MonadIO m, MonadDb m) => String -> Maybe Platform -> m ()+printPkgConfigPath = printFlagsWith buildCfgToPkgConfigPath++printIncludePath :: (MonadIO m, MonadDb m) => String -> Maybe Platform -> m ()+printIncludePath = printFlagsWith buildCfgToIncludePath++printLibPath :: (MonadIO m, MonadDb m) => String -> Maybe Platform -> m ()+printLibPath = printFlagsWith buildCfgToLibPath++parseHostIO :: MonadIO m => Maybe Platform -> m (Maybe TargetTriple)+parseHostIO (Just x) = fmap Just (parseTripleIO x)+parseHostIO Nothing  = pure Nothing++printFlagsWith :: (MonadIO m, MonadDb m) => FlagPrint -> String -> Maybe Platform -> m ()+printFlagsWith f name host = do++    parsedHost <- parseHostIO host++    maybePackage <- lookupPackage name parsedHost++    case maybePackage of+        Nothing -> indexError name+        Just p  -> liftIO (putStrLn =<< f p)++printMany :: (MonadIO m, MonadDb m) => ([BuildCfg] -> m ()) -> [String] -> Maybe Platform -> m ()+printMany f names host = do++    parsedHost <- parseHostIO host++    maybePackages <- sequenceA <$> traverse (\n -> lookupPackage n parsedHost) names++    case maybePackages of+        Nothing -> indexError (head names)+        Just ps -> f ps++printCabalFlags :: (MonadIO m, MonadDb m) => [String] -> Maybe Platform -> m ()+printCabalFlags = printMany (liftIO . putStrLn <=< (fmap unwords . traverse buildCfgToCabalFlag))++buildCfgToCabalFlag :: MonadIO m => BuildCfg -> m String+buildCfgToCabalFlag = fmap (("--extra-lib-dirs=" ++) . (</> "lib")) . buildCfgToDir++-- TODO: do something more sophisticated; allow packages to return their own+-- dir?+buildCfgToLinkerFlags :: MonadIO m => BuildCfg -> m String+buildCfgToLinkerFlags = fmap (("-L" ++) . (</> "lib")) . buildCfgToDir++buildCfgToCFlags :: MonadIO m => BuildCfg -> m String+buildCfgToCFlags = fmap (("-I" ++) . (</> "include")) . buildCfgToDir++buildCfgToPkgConfigPath :: MonadIO m => BuildCfg -> m String+buildCfgToPkgConfigPath = fmap (</> "lib" </> "pkgconfig") . buildCfgToDir++buildCfgToLibPath :: MonadIO m => BuildCfg -> m String+buildCfgToLibPath = fmap (</> "lib") . buildCfgToDir++buildCfgToIncludePath :: MonadIO m => BuildCfg -> m String+buildCfgToIncludePath = fmap (</> "include") . buildCfgToDir++packageInstalled :: (MonadIO m, MonadDb m)+                 => CPkg+                 -> Maybe TargetTriple+                 -> BuildVars+                 -> m Bool+packageInstalled pkg host b = do++    indexContents <- memIndex++    pure (pkgToBuildCfg pkg host b `S.member` _installedPackages indexContents)++lookupPackage :: (MonadIO m, MonadDb m) => String -> Maybe TargetTriple -> m (Maybe BuildCfg)+lookupPackage name host = do++    indexContents <- memIndex++    let matches = S.filter (\pkg -> buildName pkg == name && targetArch pkg == host) (_installedPackages indexContents)++    pure (S.lookupMax matches)++-- TODO: replace this with a proper/sensible database+registerPkg :: (MonadIO m, MonadDb m, MonadReader Verbosity m)+            => CPkg+            -> Maybe TargetTriple+            -> BuildVars+            -> m ()+registerPkg cpkg host b = do++    putDiagnostic ("Registering package " ++ pkgName cpkg ++ "...")++    indexFile <- pkgIndex+    indexContents <- memIndex++    let buildCfg = pkgToBuildCfg cpkg host b+        modIndex = over installedPackages (S.insert buildCfg)+        newIndex = modIndex indexContents++    modify modIndex++    liftIO $ BSL.writeFile indexFile (encode newIndex)++pkgToBuildCfg :: CPkg+              -> Maybe TargetTriple+              -> BuildVars+              -> BuildCfg+pkgToBuildCfg (CPkg n v _ _ _ _ cCmd bCmd iCmd) host bVar =+    BuildCfg n v mempty mempty host (cCmd bVar) (bCmd bVar) (iCmd bVar) -- TODO: fix pinned build deps &c.++platformString :: Maybe TargetTriple -> (FilePath -> FilePath -> FilePath)+platformString Nothing  = (</>)+platformString (Just p) = \x y -> x </> show p </> y++buildCfgToDir :: MonadIO m => BuildCfg -> m FilePath+buildCfgToDir buildCfg = do+    global <- globalPkgDir+    let hashed = showHex (abs (hash buildCfg)) mempty+        (<?>) = platformString (targetArch buildCfg)+    pure (global <?> buildName buildCfg ++ "-" ++ showVersion (buildVersion buildCfg) ++ "-" ++ hashed)++cPkgToDir :: MonadIO m+          => CPkg+          -> Maybe TargetTriple+          -> BuildVars+          -> m FilePath+cPkgToDir = buildCfgToDir .** pkgToBuildCfg
+ src/Package/C/Db/Type.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE DeriveAnyClass             #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE DerivingStrategies         #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Package.C.Db.Type ( BuildCfg (..)+                         , InstallDb (..)+                         -- * Lenses+                         , installedPackages+                         ) where++import           CPkgPrelude+import           Data.Semigroup+import qualified Data.Set       as S+import qualified Data.Text      as T+import           Package.C.Type++-- TODO: we definitely want something different here - it should allow garbage+-- collection, for one+newtype InstallDb = InstallDb { _installedPackages :: S.Set BuildCfg }+    deriving newtype (Semigroup, Monoid, Binary)++installedPackages :: Lens' InstallDb (S.Set BuildCfg)+installedPackages f s = fmap (\x -> s { _installedPackages = x }) (f (_installedPackages s))++data BuildCfg = BuildCfg { buildName       :: String+                         , buildVersion    :: Version+                         , pinnedBuildDeps :: [(T.Text, Version)]+                         , pinnedDeps      :: [(T.Text, Version)]+                         , targetArch      :: Maybe TargetTriple+                         , configureCmds   :: [ Command ]+                         , buildCmds       :: [ Command ]+                         , installCmds     :: [ Command ]+                         } deriving (Eq, Ord, Generic, Binary, Hashable)
+ src/Package/C/Dhall.hs view
@@ -0,0 +1,20 @@+module Package.C.Dhall ( getCPkg+                       , getPkgs+                       ) where++import           Dhall+import           Package.C.Dhall.Type+import           Package.C.Type.Verbosity++maybeMod :: Verbosity -> IO a -> IO a+maybeMod v | v >= Verbose = detailed+           | otherwise = id++getDhall :: Interpret a => Verbosity -> FilePath -> IO a+getDhall v = maybeMod v . inputFile auto++getCPkg :: Verbosity -> FilePath -> IO CPkg+getCPkg = getDhall++getPkgs :: Verbosity -> FilePath -> IO [CPkg]+getPkgs = getDhall
+ src/Package/C/Dhall/Type.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE DeriveAnyClass    #-}+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE OverloadedStrings #-}++module Package.C.Dhall.Type ( CPkg (..)+                            , BuildVars (..)+                            , EnvVar (..)+                            , Command (..)+                            ) where++import qualified Data.Text                        as T+import           Data.Text.Prettyprint.Doc+import           Data.Text.Prettyprint.Doc.Custom+import           Dhall+import           GHC.Natural                      (Natural)+import           Package.C.Triple.Type+import           Package.C.Type.Shared+import           Package.C.Type.Version++data BuildVars = BuildVars { installDir   :: T.Text+                           , currentDir   :: T.Text+                           , targetTriple :: Maybe TargetTriple+                           , isCross      :: Bool+                           , includeDirs  :: [ T.Text ]+                           , preloadLibs  :: [ T.Text ]+                           -- TODO: nameToLinkDir function??+                           , shareDirs    :: [ T.Text ]+                           , linkDirs     :: [ T.Text ]+                           , binDirs      :: [ T.Text ]+                           , buildOS      :: OS+                           , buildArch    :: Arch+                           , static       :: Bool+                           , cpus         :: Natural+                           } deriving (Generic, Inject)++data EnvVar = EnvVar { var :: T.Text, value :: T.Text }+            deriving (Generic, Interpret)++data Command = CreateDirectory { dir :: T.Text }+             | MakeExecutable { file :: T.Text }+             | Call { program     :: T.Text+                    , arguments   :: [T.Text]+                    , environment :: Maybe [EnvVar]+                    , procDir     :: Maybe T.Text+                    }+             | SymlinkBinary { file :: T.Text }+             | Symlink { tgt :: T.Text, linkName :: T.Text }+             | Write { contents :: T.Text, file :: T.Text }+             | CopyFile { src :: T.Text, dest :: T.Text }+             deriving (Generic, Interpret)++data CPkg = CPkg { pkgName          :: T.Text+                 , pkgVersion       :: [ Natural ]+                 , pkgUrl           :: T.Text+                 , pkgSubdir        :: T.Text+                 , pkgBuildDeps     :: [ Dep ] -- TODO: depend on target?+                 , pkgDeps          :: [ Dep ]+                 , configureCommand :: BuildVars -> [ Command ]+                 , buildCommand     :: BuildVars -> [ Command ]+                 , installCommand   :: BuildVars -> [ Command ]+                 -- TODO: add "description" field for printing+                 -- TODO: add "test" command for e.g. `make check`+                 } deriving (Generic, Interpret)++preDeps :: Doc a -> [ Dep ] -> Doc a+preDeps _ []   = ""+preDeps dep ds = hardline <> dep <+> hsep (punctuate "," (pretty . name <$> ds))++prettyDeps :: [ Dep ] -> Doc a+prettyDeps = preDeps "dependencies:"++prettyBldDeps :: [ Dep ] -> Doc a+prettyBldDeps = preDeps "build dependencies:"++instance Pretty CPkg where+    pretty (CPkg nam v url _ bds ds _ _ _) = pretty nam <##> indent 4 ("url:" <+> pretty url <##> "version:" <+> pretty (Version v) <> prettyDeps ds <> prettyBldDeps bds)
+ src/Package/C/Error.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE OverloadedStrings #-}++module Package.C.Error ( printErr+                       , unrecognized+                       , indexError+                       , corruptedDatabase+                       , unfoundPackage+                       , parseErr+                       , PackageError (..)+                       ) where++import           CPkgPrelude+import           Data.Text.Prettyprint.Doc+import           Data.Text.Prettyprint.Doc.Custom+import           Data.Text.Prettyprint.Doc.Render.Text+import           System.Exit++data PackageError = Unrecognized String+                  | IndexError String -- package name+                  | CorruptedDatabase+                  | UnfoundPackage -- TODO: this should take the package name as an argument+                  | ParseFailed String++instance Pretty PackageError where+    pretty (Unrecognized t)  = "Error: Unrecognized archive format when unpacking" <#> hang 2 (pretty t) <> hardline+    pretty (IndexError str)  = "Error: Package" <+> pretty str <+> "not found in your indices. Try 'cpkg install" <+> pretty str <> "'." <> hardline+    pretty CorruptedDatabase = "Error: Package database corrupted. Please try 'cpkg nuke'" <> hardline+    pretty UnfoundPackage    = "Error: Package not found" <> hardline+    pretty (ParseFailed str) = "Parse error:" <+> pretty str++printErr :: MonadIO m => PackageError -> m a+printErr e = liftIO (putDoc (pretty e) *> exitFailure)++unrecognized :: MonadIO m => String -> m a+unrecognized = printErr . Unrecognized++indexError :: MonadIO m => String -> m a+indexError = printErr . IndexError++corruptedDatabase :: MonadIO m => m a+corruptedDatabase = printErr CorruptedDatabase++unfoundPackage :: MonadIO m => m a+unfoundPackage = printErr UnfoundPackage++parseErr :: MonadIO m => String -> m a+parseErr = printErr . ParseFailed
+ src/Package/C/Fetch.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE OverloadedStrings #-}++module Package.C.Fetch ( fetchUrl+                       ) where++import           CPkgPrelude+import qualified Data.ByteString.Lazy    as BSL+import           Data.List               (isSuffixOf)+import           Data.Maybe              (fromJust)+import           Network.HTTP.Client+import           Network.HTTP.Client.TLS (tlsManagerSettings)+import           Network.URI+import           Package.C.Db.Register+import           Package.C.Error+import           Package.C.Logging+import           Package.C.Monad+import           Package.C.Unpack+import           System.Directory        (createDirectoryIfMissing)+import           System.FilePath         (takeFileName)++urlToCompression :: MonadIO m => String -> m Compression+urlToCompression s | ".tar.gz" `isSuffixOf` s || ".tgz" `isSuffixOf` s = pure $ Tar Gz+                   | ".tar.xz" `isSuffixOf` s = pure $ Tar Xz+                   | ".tar.bz2" `isSuffixOf` s = pure $ Tar Bz2+                   | ".tar" `isSuffixOf` s = pure $ Tar None+                   | ".zip" `isSuffixOf` s = pure Zip+                   | otherwise = unrecognized s++asFilename :: String -> Maybe String+asFilename = fmap (takeFileName . uriPath) . parseURI++cacheDir :: MonadIO m => m FilePath+cacheDir = (</> "cache") <$> globalPkgDir++fetchUrl :: String -- ^ URL+         -> String -- ^ Package name+         -> FilePath -- ^ Directory to unpack to+         -> PkgM ()+fetchUrl url name dirName = do++        let tarballName = fromJust (asFilename url)+        tarballDir <- (</> tarballName) <$> cacheDir+        shouldDownload <- not <$> liftIO (doesFileExist tarballDir)++        compression <- urlToCompression url++        response <-+            if shouldDownload+                then do+                    putNormal ("Downloading " ++ name)++                    putLoud ("from URL " ++ url)++                    manager <- liftIO $ newManager tlsManagerSettings+                    initialRequest <- liftIO $ parseRequest url+                    liftIO $ responseBody <$> httpLbs (initialRequest { method = "GET" }) manager+                else do+                    putDiagnostic ("Using cached tarball at " ++ tarballDir)+                    liftIO $ BSL.readFile tarballDir++        cacheDirExists <- liftIO (doesFileExist =<< cacheDir)+        unless cacheDirExists+            (liftIO $ createDirectoryIfMissing True =<< cacheDir)++        when shouldDownload $ do+            -- TODO: should cache/compress to .tar.xz?+            putLoud ("Caching " ++ tarballName)+            liftIO $ BSL.writeFile tarballDir response++        putNormal ("Unpacking " ++ name)++        liftIO $ unpackResponse compression dirName response
+ src/Package/C/Logging.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE FlexibleContexts #-}++module Package.C.Logging ( putNormal+                         , putDiagnostic+                         , putLoud+                         ) where++import           Control.Monad.Reader+import           Package.C.Type.Verbosity++putVerbosity :: (MonadReader Verbosity m, MonadIO m) => Verbosity -> String -> m ()+putVerbosity verb s = do+    v <- ask+    when (v >= verb)+        (liftIO (putStrLn s))++putNormal :: (MonadReader Verbosity m, MonadIO m) => String -> m ()+putNormal = putVerbosity Normal++putDiagnostic :: (MonadReader Verbosity m, MonadIO m) => String -> m ()+putDiagnostic = putVerbosity Diagnostic++putLoud :: (MonadReader Verbosity m, MonadIO m) => String -> m ()+putLoud = putVerbosity Loud
+ src/Package/C/Monad.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE ConstraintKinds  #-}+{-# LANGUAGE FlexibleContexts #-}++module Package.C.Monad ( PkgM+                       , MonadPkg+                       , runPkgM+                       ) where++import           Control.Monad.Reader+import           Control.Monad.State+import           Package.C.Db.Memory+import           Package.C.Db.Type+import           Package.C.Type.Verbosity++-- TODO: should this take a 'Maybe Platform' as well?+type PkgM = StateT InstallDb (ReaderT Verbosity IO)++type MonadPkg m = (MonadState InstallDb m, MonadReader Verbosity m, MonadIO m)++runPkgM :: Verbosity -> PkgM a -> IO a+runPkgM v act = do+    pSet <- strictIndex+    flip runReaderT v $ evalStateT act pSet
+ src/Package/C/PackageSet.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings          #-}++module Package.C.PackageSet ( PackageSet (..)+                            , PackId+                            , pkgsM+                            , displayPackageSet+                            ) where++import           CPkgPrelude+import           Data.Containers.ListUtils+import           Data.List                             (intersperse)+import qualified Data.Map                              as M+import qualified Data.Text                             as T+import           Data.Text.Prettyprint.Doc+import           Data.Text.Prettyprint.Doc.Custom+import           Data.Text.Prettyprint.Doc.Render.Text+import           Dhall+import qualified Package.C.Dhall.Type                  as Dhall+import           Package.C.Error+import           Package.C.Type+import           Package.C.Type.Tree++defaultPackageSetDhall :: Maybe String -> IO PackageSetDhall+defaultPackageSetDhall (Just pkSet) = input auto (T.pack pkSet)+defaultPackageSetDhall Nothing      = input auto "https://raw.githubusercontent.com/vmchale/cpkg/master/pkgs/pkg-set.dhall"++displayPackageSet :: Maybe String -> IO ()+displayPackageSet = putDoc . pretty <=< defaultPackageSetDhall++newtype PackageSetDhall = PackageSetDhall [ Dhall.CPkg ]+    deriving Interpret++instance Pretty PackageSetDhall where+    pretty (PackageSetDhall set) = vdisplay (intersperse hardline (pretty <$> set)) <> hardline++newtype PackageSet = PackageSet (M.Map T.Text CPkg)++type PackId = T.Text++packageSetDhallToPackageSet :: PackageSetDhall -> PackageSet+packageSetDhallToPackageSet (PackageSetDhall pkgs'') =+    let names = Dhall.pkgName <$> pkgs''+        pkgs' = cPkgDhallToCPkg <$> pkgs''++        in PackageSet $ M.fromList (zip names pkgs')++getDeps :: PackId -> PackageSet -> Maybe (DepTree PackId)+getDeps pkgName' set@(PackageSet ps) = do+    cpkg <- M.lookup pkgName' ps+    let depNames = name <$> pkgDeps cpkg+        bldDepNames = name <$> pkgBuildDeps cpkg+        ds = nubOrd depNames+        bds = nubOrd bldDepNames+    nextDeps <- traverse (\p -> getDeps p set) ds+    nextBldDeps <- traverse (\p -> asBldDep <$> getDeps p set) bds+    pure $ DepNode pkgName' (nextDeps ++ nextBldDeps)++-- TODO: use dfsForest but check for cycles+pkgPlan :: PackId -> PackageSet -> Maybe (DepTree PackId)+pkgPlan = getDeps++pkgs :: PackId -> PackageSet -> Maybe (DepTree CPkg)+pkgs pkId set@(PackageSet pset) = do+    plan <- pkgPlan pkId set+    traverse (`M.lookup` pset) plan++pkgsM :: PackId -> Maybe String -> IO (DepTree CPkg)+pkgsM pkId pkSet = do+    pks <- pkgs pkId . packageSetDhallToPackageSet <$> defaultPackageSetDhall pkSet+    case pks of+        Just x  -> pure x+        Nothing -> unfoundPackage
+ src/Package/C/Triple.hs view
@@ -0,0 +1,14 @@+module Package.C.Triple ( -- * Types+                          TargetTriple (..)+                        , Arch (..)+                        , OS (..)+                        , Manufacturer (..)+                        , ABI (..)+                        -- * Parsers+                        , parseTriple+                        -- * Helper functions+                        , parseTripleIO+                        ) where++import           Package.C.Triple.Parse+import           Package.C.Triple.Type
+ src/Package/C/Triple/Parse.hs view
@@ -0,0 +1,87 @@+module Package.C.Triple.Parse ( parseTriple+                              , parseTripleIO+                              ) where++import           CPkgPrelude+import           Package.C.Error+import           Package.C.Triple.Type+import           Text.Megaparsec+import           Text.Megaparsec.Char++type Parser = Parsec Void String++parseTripleIO :: MonadIO m => String -> m TargetTriple+parseTripleIO = parseIO parseTriple++parseIO :: MonadIO m => Parser a -> String -> m a+parseIO p str =+    case parse p "(none)" str of+        Right x  -> pure x+        Left err -> parseErr (errorBundlePretty err)++parseTriple :: Parser TargetTriple+parseTriple = TargetTriple+    <$> parseArch+    <*> optional (try (char '-' *> parseManufacturer))+    <*> (char '-' *> parseOS)+    <*> optional (char '-' *> parseABI)++tryString :: String -> Parser String+tryString = try . string++parseArch :: Parser Arch+parseArch =+        (tryString "x86_64" $> X64)+    <|> (tryString "armv7l" $> Arm)+    <|> (tryString "arm" $> Arm)+    <|> (tryString "aarch64" $> AArch)+    <|> (tryString "riscv64" $> RISCV64)+    <|> (tryString "powerpc64le" $> PowerPC64le)+    <|> (tryString "powerpc64" $> PowerPC64)+    <|> (tryString "powerpc" $> PowerPC)+    <|> (tryString "sparc64" $> Sparc64)+    <|> (tryString "s390x" $> S390x)+    <|> (tryString "alpha" $> Alpha)+    <|> (tryString "m68k" $> M68k)+    <|> (tryString "mips64el" $> Mips64El)+    <|> (tryString "mips64" $> Mips64)+    <|> (tryString "mipsel" $> MipsEl)+    <|> (tryString "mips" $> Mips)+    <|> (tryString "i686" $> X86)+    <|> (tryString "sh4" $> SH4)+    <|> (tryString "hppa64" $> HPPA64)+    <|> (tryString "hppa" $> HPPA)++parseManufacturer :: Parser Manufacturer+parseManufacturer =+        (tryString "unknown" $> Unknown)+    <|> (tryString "apple" $> Apple)+    <|> (tryString "ibm" $> IBM)+    <|> (tryString "pc" $> PC)++parseOS :: Parser OS+parseOS =+        (tryString "darwin" $> Darwin)+    <|> (tryString "dragonfly" $> Dragonfly)+    <|> (tryString "freebsd" $> FreeBSD)+    <|> (tryString "linux" $> Linux)+    <|> (tryString "openbsd" $> OpenBSD)+    <|> (tryString "netbsd" $> NetBSD)+    <|> (tryString "solaris" $> Solaris)+    <|> (tryString "w64" $> Windows)+    <|> (tryString "redox" $> Redox)+    <|> (tryString "haiku" $> Haiku)+    <|> (tryString "ios" $> IOS)+    <|> (tryString "aix" $> AIX)+    <|> (tryString "hurd" $> Hurd)+    <|> (tryString "android" $> Android)+    <|> (tryString "none" $> NoOs)++parseABI :: Parser ABI+parseABI =+        (tryString "gnueabihf" $> GNUeabihf)+    <|> (tryString "gnuabi64" $> GNUabi64)+    <|> (tryString "gnueabi" $> GNUeabi)+    <|> (tryString "gnuspe" $> GNUspe)+    <|> (tryString "gnu" $> GNU)+    <|> (tryString "mingw32" $> MinGw)
+ src/Package/C/Triple/Type.hs view
@@ -0,0 +1,136 @@+{-# LANGUAGE DeriveAnyClass    #-}+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE OverloadedStrings #-}++module Package.C.Triple.Type ( TargetTriple (..)+                             , Manufacturer (..)+                             , Arch (..)+                             , ABI (..)+                             , OS (..)+                             ) where++import           CPkgPrelude+import           Data.Text.Prettyprint.Doc.Custom++-- TODO: are the derived Binary instances inefficient? possibly replace them+-- with handwritten instances...+data TargetTriple = TargetTriple { arch         :: Arch+                                 , manufacturer :: Maybe Manufacturer+                                 , os           :: OS+                                 , abi          :: Maybe ABI+                                 }+                                 deriving (Eq, Ord, Hashable, Binary, Generic, Inject)++instance Pretty TargetTriple where+    pretty (TargetTriple a (Just m) o (Just ab)) = dashed [pretty a, pretty m, pretty o, pretty ab]+    pretty (TargetTriple a Nothing o (Just ab))  = dashed [pretty a, pretty o, pretty ab]+    pretty (TargetTriple a (Just m) o Nothing)   = dashed [pretty a, pretty m, pretty o]+    pretty (TargetTriple a Nothing o Nothing)    = dashed [pretty a, pretty o]++instance Show TargetTriple where+    show = show . pretty++data Manufacturer = Unknown+                  | Apple+                  | IBM+                  | PC+                  deriving (Eq, Ord, Hashable, Binary, Generic, Inject)++instance Pretty Manufacturer where+    pretty Unknown = "unknown"+    pretty Apple   = "apple"+    pretty IBM     = "ibm"+    pretty PC      = "pc"++data Arch = X64+          | AArch+          | Arm+          | RISCV64+          | PowerPC+          | PowerPC64+          | PowerPC64le+          | Sparc64+          | S390x+          | Alpha+          | M68k+          | Mips+          | MipsEl+          | Mips64+          | Mips64El+          | X86+          | SH4+          | HPPA+          | HPPA64+          deriving (Eq, Ord, Hashable, Binary, Generic, Inject)++instance Pretty Arch where+    pretty X64         = "x86_64"+    pretty AArch       = "aarch64"+    pretty Arm         = "arm"+    pretty RISCV64     = "riscv64"+    pretty PowerPC     = "powerpc"+    pretty PowerPC64   = "powerpc64"+    pretty PowerPC64le = "powerpc64le"+    pretty Sparc64     = "sparc64"+    pretty S390x       = "s390x"+    pretty Alpha       = "alpha"+    pretty M68k        = "m68k"+    pretty Mips        = "mips"+    pretty MipsEl      = "mipsel"+    pretty Mips64      = "mips64"+    pretty Mips64El    = "mips64el"+    pretty X86         = "i686"+    pretty SH4         = "sh4"+    pretty HPPA        = "hppa"+    pretty HPPA64      = "hppa64"++data ABI = GNU+         | GNUabi64+         | GNUeabi+         | GNUeabihf+         | GNUspe+         | MinGw+         deriving (Eq, Ord, Hashable, Binary, Generic, Inject)++instance Pretty ABI where+    pretty GNU       = "gnu"+    pretty GNUabi64  = "gnuabi64"+    pretty GNUeabi   = "gnueabi"+    pretty GNUeabihf = "gnueabihf"+    pretty GNUspe    = "gnuspe"+    pretty MinGw     = "mingw32"++data OS = Darwin+        | Dragonfly+        | FreeBSD+        | Linux+        | OpenBSD+        | NetBSD+        | Solaris+        | Windows+        | Redox+        | Haiku+        | IOS+        | AIX+        | Hurd+        | Android+        | NoOs+        deriving (Eq, Ord, Hashable, Binary, Generic, Inject)+        -- IRIX? OpenSSL OSes?++instance Pretty OS where+    pretty Darwin    = "darwin"+    pretty Dragonfly = "dragonfly"+    pretty FreeBSD   = "freebsd"+    pretty Linux     = "linux"+    pretty OpenBSD   = "openbsd"+    pretty NetBSD    = "netbsd"+    pretty Solaris   = "solaris"+    pretty Windows   = "w64"+    pretty Redox     = "redox"+    pretty Haiku     = "haiku"+    pretty IOS       = "ios"+    pretty AIX       = "aix"+    pretty Hurd      = "hurd"+    pretty Android   = "android"+    pretty NoOs      = "none"
+ src/Package/C/Type.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric  #-}++module Package.C.Type ( CPkg (..)+                      , BuildVars (..)+                      , Verbosity (..)+                      , EnvVar (..)+                      , Command (..)+                      , Dep (..)+                      , Version (..)+                      , OS (..)+                      , TargetTriple (..)+                      -- * Helper functions+                      , cPkgDhallToCPkg+                      , showVersion+                      ) where++import           CPkgPrelude+import qualified Data.Text                as T+import           GHC.Generics             (Generic)+import qualified Package.C.Dhall.Type     as Dhall+import           Package.C.Triple.Type+import           Package.C.Type.Shared+import           Package.C.Type.Vars+import           Package.C.Type.Verbosity+import           Package.C.Type.Version++data EnvVar = EnvVar { var :: String, value :: String }+            deriving (Eq, Ord, Generic, Binary, Hashable)++data Command = CreateDirectory { dir :: String }+             | MakeExecutable { file :: String }+             | Call { program     :: String+                    , arguments   :: [String]+                    , environment :: Maybe [EnvVar]+                    , procDir     :: Maybe String+                    }+             | SymlinkBinary { file :: String }+             | Symlink { tgt :: String, linkName :: String }+             | Write { contents :: T.Text, file :: FilePath }+             | CopyFile { src :: FilePath, dest :: FilePath }+             deriving (Eq, Ord, Generic, Binary, Hashable)++-- TODO: build script should take OS as an argument?+-- That way we can use make/gmake where we want it+data CPkg = CPkg { pkgName          :: String+                 , pkgVersion       :: Version+                 , pkgUrl           :: String+                 , pkgSubdir        :: String+                 , pkgBuildDeps     :: [ Dep ]+                 , pkgDeps          :: [ Dep ]+                 , configureCommand :: BuildVars -> [ Command ]+                 , buildCommand     :: BuildVars -> [ Command ]+                 , installCommand   :: BuildVars -> [ Command ]+                 }++envVarDhallToEnvVar :: Dhall.EnvVar -> EnvVar+envVarDhallToEnvVar (Dhall.EnvVar ev x) = EnvVar (T.unpack ev) (T.unpack x)++commandDhallToCommand :: Dhall.Command -> Command+commandDhallToCommand (Dhall.CreateDirectory d)   = CreateDirectory (T.unpack d)+commandDhallToCommand (Dhall.MakeExecutable exe)  = MakeExecutable (T.unpack exe)+commandDhallToCommand (Dhall.Call p as env proc)  = Call (T.unpack p) (T.unpack <$> as) (fmap envVarDhallToEnvVar <$> env) (T.unpack <$> proc)+commandDhallToCommand (Dhall.SymlinkBinary b)     = SymlinkBinary (T.unpack b)+commandDhallToCommand (Dhall.Write out fp)        = Write out (T.unpack fp)+commandDhallToCommand (Dhall.CopyFile src' dest') = CopyFile (T.unpack src') (T.unpack dest')+commandDhallToCommand (Dhall.Symlink t l)         = Symlink (T.unpack t) (T.unpack l)++buildVarsToDhallBuildVars :: BuildVars -> Dhall.BuildVars+buildVarsToDhallBuildVars (BuildVars dir' cd tgt' cross incls prelds shr lds bins os' arch' sta nproc) = Dhall.BuildVars (T.pack dir') (T.pack cd) tgt' cross (T.pack <$> incls) (T.pack <$> prelds) (T.pack <$> shr) (T.pack <$> lds) (T.pack <$> bins) os' arch' sta (fromIntegral nproc)++cPkgDhallToCPkg :: Dhall.CPkg -> CPkg+cPkgDhallToCPkg (Dhall.CPkg n v url subdir bldDeps deps cfgCmd buildCmd installCmd) =+    CPkg (T.unpack n) (Version v) (T.unpack url) (T.unpack subdir) bldDeps deps configure build install++    where configure cfg = commandDhallToCommand <$> cfgCmd (buildVarsToDhallBuildVars cfg)+          build cfg = commandDhallToCommand <$> buildCmd (buildVarsToDhallBuildVars cfg)+          install cfg = commandDhallToCommand <$> installCmd (buildVarsToDhallBuildVars cfg)
+ src/Package/C/Type/Shared.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE DeriveAnyClass     #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DerivingStrategies #-}+++module Package.C.Type.Shared ( VersionBound (..)+                             , Dep (..)+                             ) where++import qualified Data.Text              as T+import           Dhall+import           Package.C.Type.Version++data VersionBound = Lower { lower :: Version }+                  | Upper { upper :: Version }+                  | LowerUpper { lower :: Version, upper :: Version }+                  | NoBound+                  deriving (Generic, Interpret)++data Dep = Dep { name  :: T.Text+               , bound :: VersionBound+               } deriving (Generic, Interpret)
+ src/Package/C/Type/Tree.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE DeriveFoldable    #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE TypeFamilies      #-}++module Package.C.Type.Tree ( DepTree (..)+                           , DepTreeF (..)+                           , asBldDep+                           ) where++import           Control.Recursion++data DepTree p = DepNode p [DepTree p]+               | BldDepNode p [DepTree p]+    deriving (Functor, Foldable, Traversable)++data DepTreeF p x = DepNodeF { self :: p, deps :: [x] }+                  | BldDepNodeF { self :: p, deps :: [x] }+                  deriving (Functor, Foldable, Traversable)++type instance Base (DepTree a) = DepTreeF a++instance Recursive (DepTree a) where+    project (DepNode p ps)    = DepNodeF p ps+    project (BldDepNode p ps) = BldDepNodeF p ps++asBldDep :: DepTree p -> DepTree p+asBldDep (DepNode p ps)    = BldDepNode p (fmap asBldDep ps)+asBldDep (BldDepNode p ps) = BldDepNode p (fmap asBldDep ps)
+ src/Package/C/Type/Vars.hs view
@@ -0,0 +1,19 @@+module Package.C.Type.Vars ( BuildVars (..)+                           ) where++import           Package.C.Triple.Type++data BuildVars = BuildVars { installDir   :: FilePath+                           , currentDir   :: FilePath+                           , targetTriple :: Maybe TargetTriple+                           , isCross      :: Bool+                           , includeDirs  :: [ FilePath ]+                           , preloadLibs  :: [ FilePath ]+                           , shareDirs    :: [ FilePath ]+                           , linkDirs     :: [ FilePath ]+                           , binDirs      :: [ FilePath ]+                           , buildOS      :: OS -- ^ See [here](https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html) for terminology. This is the OS of the system we are building on.+                           , buildArch    :: Arch+                           , static       :: Bool+                           , cpus         :: Int+                           }
+ src/Package/C/Type/Verbosity.hs view
@@ -0,0 +1,9 @@+module Package.C.Type.Verbosity ( Verbosity (..)+                                ) where++data Verbosity = Silent -- ^ Display nothing+               | Normal -- ^ Display progress information+               | Verbose -- ^ Display stderr from builds+               | Loud -- ^ Display stdout and stderr from builds+               | Diagnostic -- ^ Display stdout and stderr from builds, and display debug information+               deriving (Eq, Ord)
+ src/Package/C/Type/Version.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings          #-}++module Package.C.Type.Version ( Version (..)+                              , showVersion+                              ) where++import           CPkgPrelude+import           Data.List   (intercalate)++newtype Version = Version [ Natural ]+    deriving (Eq, Ord, Interpret, Binary, Hashable)++showVersion :: Version -> String+showVersion (Version v) = intercalate "." (show <$> v)++instance Pretty Version where+    pretty (Version v) = fold (punctuate "." (pretty <$> v))
+ src/Package/C/Unpack.hs view
@@ -0,0 +1,40 @@+module Package.C.Unpack ( unpackResponse+                        , Compression (..)+                        , TarCompress (..)+                        ) where++import qualified Codec.Archive.Tar      as Tar+import           Codec.Archive.Zip      (ZipOption (..), extractFilesFromArchive, toArchive)+import qualified Codec.Compression.BZip as Bzip+import qualified Codec.Compression.GZip as Gzip+import qualified Codec.Compression.Lzma as Lzma+import qualified Data.ByteString.Lazy   as BSL++data TarCompress = Gz+                 | Xz+                 | Bz2+                 | None++data Compression = Tar TarCompress+                 | Zip+++getCompressor :: TarCompress -> BSL.ByteString -> BSL.ByteString+getCompressor Gz   = Gzip.decompress+getCompressor None = id+getCompressor Xz   = Lzma.decompress+getCompressor Bz2  = Bzip.decompress++tarResponse :: TarCompress -> FilePath -> BSL.ByteString -> IO ()+tarResponse compressScheme dirName response =+    let f = Tar.unpack dirName . Tar.read . getCompressor compressScheme+    in f response++zipResponse :: FilePath -> BSL.ByteString -> IO ()+zipResponse dirName response = do+    let options = OptDestination dirName+    extractFilesFromArchive [options] (toArchive response)++unpackResponse :: Compression -> FilePath -> BSL.ByteString -> IO ()+unpackResponse (Tar tarCmp) fp response = tarResponse tarCmp fp response+unpackResponse Zip fp response          = zipResponse fp response
+ src/System/Directory/Executable.cpphs view
@@ -0,0 +1,13 @@+module System.Directory.Executable ( mkExecutable ) where++import           System.Directory++#ifdef mingw32_HOST_OS+mkExecutable :: FilePath -> IO ()+mkExecutable = mempty+#else+mkExecutable :: FilePath -> IO ()+mkExecutable fp = do+    perms <- getPermissions fp+    setPermissions fp (setOwnerExecutable True perms)+#endif
+ src/System/Process/Ext.hs view
@@ -0,0 +1,27 @@+module System.Process.Ext ( waitProcess+                          ) where++import           Control.Monad.Reader     (ask)+import           CPkgPrelude+import           Package.C.Monad+import           Package.C.Type.Verbosity+import           System.Exit              (ExitCode (ExitSuccess), exitWith)+import           System.Process++handleExit :: ExitCode -> IO ()+handleExit ExitSuccess = mempty+handleExit x           = exitWith x++verbosityErr :: Verbosity -> StdStream+verbosityErr v | v >= Verbose = Inherit+verbosityErr _ = CreatePipe++waitProcess :: CreateProcess -> PkgM ()+waitProcess proc' = do+    v <- ask+    if v >= Loud+        then do+            (_, _, _, r) <- liftIO $ createProcess (proc' { std_out = Inherit, std_err = Inherit })+            liftIO (handleExit =<< waitForProcess r)+        else void $ liftIO $ readCreateProcess (proc' { std_err = verbosityErr v }) mempty+
+ test/Spec.hs view
@@ -0,0 +1,18 @@+import           Package.C+import           Test.Hspec+import           Test.Hspec.Megaparsec+import           Text.Megaparsec++parseHelper :: String -> TargetTriple -> SpecWith ()+parseHelper str tgt' =+    parallel $ it "should work on arm-linux-gnueabihf" $+        parse parseTriple "(none)" str+            `shouldParse` tgt'++main :: IO ()+main = hspec $+    describe "parseTriple" $ do+        parseHelper "arm-linux-gnueabihf" $ TargetTriple Arm Nothing Linux (Just GNUeabihf)+        parseHelper "mips64el-linux-gnuabi64" $ TargetTriple Mips64El Nothing Linux (Just GNUabi64)+        parseHelper "mips64-linux-gnu" $ TargetTriple Mips64 Nothing Linux (Just GNU)+        parseHelper "x86_64-unknown-redox" $ TargetTriple X64 (Just Unknown) Redox Nothing