├── Makefile
├── .hspec
├── cabal.project
├── .gitignore
├── bash
├── profile-install
├── haddocks
├── pre-commit
├── tests
└── builds
├── .gitattributes
├── src
├── Package
│ ├── C
│ │ ├── Db
│ │ │ ├── Monad.hs
│ │ │ ├── Memory.hs
│ │ │ ├── Type.hs
│ │ │ ├── GarbageCollect.hs
│ │ │ └── Register.hs
│ │ ├── Type
│ │ │ ├── Verbosity.hs
│ │ │ ├── Version.hs
│ │ │ ├── Shared.hs
│ │ │ ├── Vars.hs
│ │ │ └── Tree.hs
│ │ ├── Triple.hs
│ │ ├── Dhall.hs
│ │ ├── Monad.hs
│ │ ├── Build
│ │ │ ├── OS.hs
│ │ │ └── Tree.hs
│ │ ├── Logging.hs
│ │ ├── Unpack.hs
│ │ ├── Error.hs
│ │ ├── Fetch.hs
│ │ ├── Triple
│ │ │ ├── Parse.hs
│ │ │ └── Type.hs
│ │ ├── Dhall
│ │ │ └── Type.hs
│ │ ├── PackageSet.hs
│ │ ├── Type.hs
│ │ └── Build.hs
│ └── C.hs
├── System
│ ├── Directory
│ │ └── Executable.cpphs
│ └── Process
│ │ └── Ext.hs
├── Data
│ └── Text
│ │ └── Prettyprint
│ │ └── Doc
│ │ └── Custom.hs
└── CPkgPrelude.hs
├── .ctags
├── cabal.project.cross
├── pkgs
└── patches
│ ├── make.patch
│ ├── xproto.patch
│ ├── xextproto.patch
│ ├── scrnsaverproto.patch
│ ├── xineramaproto.patch
│ ├── renderproto.patch
│ ├── intltool.patch
│ ├── pHash.patch
│ └── m4.patch
├── .stylish-haskell.yaml
├── test
└── Spec.hs
├── .hlint.yaml
├── LICENSE
├── CHANGELOG.md
├── dhall
├── cpkg-types.dhall
└── cpkg-prelude.dhall
├── cpkg.cabal
├── app
└── Main.hs
├── TODO.md
└── README.md
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: docs
2 |
3 | docs:
4 | dhall-docs --input dhall --output-link docs
5 |
--------------------------------------------------------------------------------
/.hspec:
--------------------------------------------------------------------------------
1 | --fail-fast
2 | --failure-report .hspec-failures
3 | --rerun
4 | --rerun-all-on-success
5 |
--------------------------------------------------------------------------------
/cabal.project:
--------------------------------------------------------------------------------
1 | packages: ./
2 | constraints: cpkg +development
3 | , zlib +pkg-config
4 |
5 | max-backjumps: 40000
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .ghc.environment.*
3 | .hspec-failures
4 | tags
5 | dist
6 | dist-*
7 | doc
8 | *.prof
9 | *.hp
10 | *.eventlog
11 |
--------------------------------------------------------------------------------
/bash/profile-install:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cabal build exe:cpkg -w ghc-8.8.2 --enable-profiling
4 | cp $(fd cpkg$ -t x -I) ~/.local/bin/cpkg-prof
5 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.cpphs linguist-language=Haskell
2 | *.hsc2hs linguist-language=Haskell
3 | *.c2hs linguist-language=Haskell
4 | *.gc linguist-language=Haskell
5 |
--------------------------------------------------------------------------------
/bash/haddocks:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e pipefail
4 | DOCS_PATH=$(PKG_CONFIG_PATH=$(cpkg dump pkg-config libarchive) cabal haddock -w ghc-8.6.5 --haddock-for-hackage | tail -n1)
5 | cabal upload --publish -d "$DOCS_PATH"
6 |
--------------------------------------------------------------------------------
/src/Package/C/Db/Monad.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE ConstraintKinds #-}
2 |
3 | module Package.C.Db.Monad ( MonadDb
4 | ) where
5 |
6 | import Control.Monad.State
7 | import Package.C.Db.Type
8 |
9 | type MonadDb = MonadState InstallDb
10 |
--------------------------------------------------------------------------------
/.ctags:
--------------------------------------------------------------------------------
1 | --langdef=DHALL
2 | --langmap=DHALL:.dhall
3 | --regex-DHALL=/let *([[:lower:]][[:alnum:]_]+)/\1/f,function/
4 | --regex-DHALL=/let *([[:upper:]][[:alnum:]_]+)/\1/t,type/
5 | --regex-DHALL=/< *([[:upper:]][[:alnum:]_]+)/\1/t,type/
6 | --regex-DHALL=/\| *([[:upper:]][[:alnum:]_]+)/\1/t,type/
7 |
--------------------------------------------------------------------------------
/cabal.project.cross:
--------------------------------------------------------------------------------
1 | packages: ./
2 |
3 | constraints: dhall +cross
4 | , half +cross
5 | , libarchive +cross
6 | , libarchive >= 1.0.5.1
7 |
8 | source-repository-package
9 | type: git
10 | tag: 2cb1e838620dbcedaa5e1d461c6c67dd56d6343d
11 | location: https://github.com/ekmett/half.git
12 |
--------------------------------------------------------------------------------
/pkgs/patches/make.patch:
--------------------------------------------------------------------------------
1 | --- glob/glob.c 2013-10-20 17:14:38.000000000 +0000
2 | +++ glob/glob.c 2018-09-18 10:16:03.860886356 +0000
3 | @@ -208,7 +208,7 @@
4 | #endif /* __GNU_LIBRARY__ || __DJGPP__ */
5 |
6 |
7 | -#if !defined __alloca && !defined __GNU_LIBRARY__
8 | +#if !defined __alloca && defined __GNU_LIBRARY__
9 |
10 | # ifdef __GNUC__
11 | # undef alloca
12 |
--------------------------------------------------------------------------------
/src/System/Directory/Executable.cpphs:
--------------------------------------------------------------------------------
1 | module System.Directory.Executable ( mkExecutable ) where
2 |
3 | import System.Directory
4 |
5 | #ifdef mingw32_HOST_OS
6 | mkExecutable :: FilePath -> IO ()
7 | mkExecutable = mempty
8 | #else
9 | mkExecutable :: FilePath -> IO ()
10 | mkExecutable fp = do
11 | perms <- getPermissions fp
12 | setPermissions fp (setOwnerExecutable True perms)
13 | #endif
14 |
--------------------------------------------------------------------------------
/bash/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # This is the pre-commit hook I use, provided for sake of other users here
4 | # It includes one check (viz., Dhall typechecking) and a perl one-liner to
5 | # update the repository's linecount
6 |
7 | set -e
8 | cabal new-run cpkg -w ghc-8.6.5 -- check-set pkgs/pkg-set.dhall
9 | cabal new-test -w ghc-8.6.5
10 | echo ':ctags' | cabal new-repl -w ghc-8.6.5
11 | perl -0777 -i -pe 's/```\n----.*```/```\n'"$(poly -c)"'\n```/igs' README.md
12 |
--------------------------------------------------------------------------------
/src/Package/C/Type/Verbosity.hs:
--------------------------------------------------------------------------------
1 | module Package.C.Type.Verbosity ( Verbosity (..)
2 | ) where
3 |
4 | data Verbosity = Silent -- ^ Display nothing
5 | | Normal -- ^ Display progress information
6 | | Verbose -- ^ Display stderr from builds
7 | | Loud -- ^ Display stdout and stderr from builds
8 | | Diagnostic -- ^ Display stdout and stderr from builds, and display debug information
9 | deriving (Eq, Ord)
10 |
--------------------------------------------------------------------------------
/pkgs/patches/xproto.patch:
--------------------------------------------------------------------------------
1 | --- config.sub 2019-04-27 16:40:36.266089495 -0500
2 | +++ config.sub 2019-04-27 16:41:44.593275058 -0500
3 | @@ -240,7 +240,7 @@
4 | | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
5 | | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
6 | | am33_2.0 \
7 | - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
8 | + | arc | aarch64 | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
9 | | bfin \
10 | | c4x | clipper \
11 | | d10v | d30v | dlx | dsp16xx \
12 |
--------------------------------------------------------------------------------
/src/Package/C/Triple.hs:
--------------------------------------------------------------------------------
1 | module Package.C.Triple ( -- * Types
2 | TargetTriple (..)
3 | , Arch (..)
4 | , OS (..)
5 | , Manufacturer (..)
6 | , ABI (..)
7 | -- * Parsers
8 | , parseTriple
9 | -- * Helper functions
10 | , parseTripleIO
11 | ) where
12 |
13 | import Package.C.Triple.Parse
14 | import Package.C.Triple.Type
15 |
--------------------------------------------------------------------------------
/pkgs/patches/xextproto.patch:
--------------------------------------------------------------------------------
1 | --- config.sub 2019-04-27 17:01:47.137694014 -0500
2 | +++ config.sub 2019-04-27 17:02:05.329622757 -0500
3 | @@ -249,7 +249,7 @@
4 | | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
5 | | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
6 | | am33_2.0 \
7 | - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
8 | + | arc | aarch64 | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
9 | | bfin \
10 | | c4x | clipper \
11 | | d10v | d30v | dlx | dsp16xx \
12 |
--------------------------------------------------------------------------------
/pkgs/patches/scrnsaverproto.patch:
--------------------------------------------------------------------------------
1 | --- config.sub 2012-03-22 22:49:47.000000000 -0500
2 | +++ config.sub 2019-04-28 04:52:47.247723846 -0500
3 | @@ -250,7 +250,7 @@
4 | | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
5 | | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
6 | | am33_2.0 \
7 | - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
8 | + | arc | aarch64 | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
9 | | bfin \
10 | | c4x | clipper \
11 | | d10v | d30v | dlx | dsp16xx \
12 |
--------------------------------------------------------------------------------
/pkgs/patches/xineramaproto.patch:
--------------------------------------------------------------------------------
1 | --- config.sub 2009-10-01 05:35:23.000000000 -0500
2 | +++ config.sub 2019-04-28 04:57:15.837809557 -0500
3 | @@ -242,7 +242,7 @@
4 | | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
5 | | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
6 | | am33_2.0 \
7 | - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
8 | + | arc | aarch64 | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
9 | | bfin \
10 | | c4x | clipper \
11 | | d10v | d30v | dlx | dsp16xx \
12 |
--------------------------------------------------------------------------------
/pkgs/patches/renderproto.patch:
--------------------------------------------------------------------------------
1 | --- config.sub 2010-08-10 09:11:53.000000000 -0500
2 | +++ config.sub.new 2019-04-27 17:18:57.730988579 -0500
3 | @@ -248,7 +248,7 @@
4 | | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
5 | | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
6 | | am33_2.0 \
7 | - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
8 | + | arc | aarch64 | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
9 | | bfin \
10 | | c4x | clipper \
11 | | d10v | d30v | dlx | dsp16xx \
12 |
--------------------------------------------------------------------------------
/.stylish-haskell.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | steps:
3 | - simple_align:
4 | cases: true
5 | top_level_patterns: true
6 | records: true
7 | - imports:
8 | align: global
9 | list_align: after_alias
10 | pad_module_names: true
11 | long_list_align: inline
12 | empty_list_align: inherit
13 | list_padding: 4
14 | separate_lists: true
15 | space_surround: false
16 | - language_pragmas:
17 | style: vertical
18 | align: true
19 | remove_redundant: false
20 |
21 | - trailing_whitespace: {}
22 | columns: 160
23 | newline: native
24 | language_extensions: [CPP]
25 |
--------------------------------------------------------------------------------
/src/Package/C/Dhall.hs:
--------------------------------------------------------------------------------
1 | module Package.C.Dhall ( getCPkg
2 | , getPkgs
3 | ) where
4 |
5 | import Dhall
6 | import Package.C.Dhall.Type
7 | import Package.C.Type.Verbosity
8 |
9 | maybeMod :: Verbosity -> IO a -> IO a
10 | maybeMod v | v >= Verbose = detailed
11 | | otherwise = id
12 |
13 | getDhall :: FromDhall a => Verbosity -> FilePath -> IO a
14 | getDhall v = maybeMod v . inputFile auto
15 |
16 | getCPkg :: Verbosity -> FilePath -> IO CPkg
17 | getCPkg = getDhall
18 |
19 | getPkgs :: Verbosity -> FilePath -> IO [CPkg]
20 | getPkgs = getDhall
21 |
--------------------------------------------------------------------------------
/src/Package/C/Type/Version.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-}
2 | {-# LANGUAGE OverloadedStrings #-}
3 |
4 | module Package.C.Type.Version ( Version (..)
5 | , showVersion
6 | ) where
7 |
8 | import CPkgPrelude
9 | import Data.List (intercalate)
10 |
11 | newtype Version = Version [ Natural ]
12 | deriving (Eq, Ord, FromDhall, Binary, Hashable)
13 |
14 | showVersion :: Version -> String
15 | showVersion (Version v) = intercalate "." (show <$> v)
16 |
17 | instance Pretty Version where
18 | pretty (Version v) = fold (punctuate "." (pretty <$> v))
19 |
--------------------------------------------------------------------------------
/src/Data/Text/Prettyprint/Doc/Custom.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE OverloadedStrings #-}
2 |
3 | module Data.Text.Prettyprint.Doc.Custom ( (<#>)
4 | , (<##>)
5 | , vdisplay
6 | , dashed
7 | ) where
8 |
9 | import Data.Foldable (foldl')
10 | import Data.Text.Prettyprint.Doc
11 |
12 | infixr 5 <#>
13 | infixr 5 <##>
14 |
15 | (<#>) :: Doc a -> Doc a -> Doc a
16 | (<#>) a b = a <> line <> b
17 |
18 | (<##>) :: Doc a -> Doc a -> Doc a
19 | (<##>) a b = a <> hardline <> b
20 |
21 | vdisplay :: [Doc a] -> Doc a
22 | vdisplay = foldl' (<#>) mempty
23 |
24 | dashed :: [Doc a] -> Doc a
25 | dashed = concatWith (\x y -> x <> "-" <> y)
26 |
--------------------------------------------------------------------------------
/src/Package/C/Monad.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE ConstraintKinds #-}
2 | {-# LANGUAGE FlexibleContexts #-}
3 |
4 | module Package.C.Monad ( PkgM
5 | , MonadPkg
6 | , runPkgM
7 | ) where
8 |
9 | import Control.Monad.Reader
10 | import Control.Monad.State
11 | import Package.C.Db.Memory
12 | import Package.C.Db.Type
13 | import Package.C.Type.Verbosity
14 |
15 | -- TODO: should this take a 'Maybe Platform' as well?
16 | type PkgM = StateT InstallDb (ReaderT Verbosity IO)
17 |
18 | type MonadPkg m = (MonadState InstallDb m, MonadReader Verbosity m, MonadIO m)
19 |
20 | runPkgM :: Verbosity -> PkgM a -> IO a
21 | runPkgM v act = do
22 | pSet <- strictIndex
23 | flip runReaderT v $ evalStateT act pSet
24 |
--------------------------------------------------------------------------------
/src/Package/C/Build/OS.hs:
--------------------------------------------------------------------------------
1 | module Package.C.Build.OS ( dhallOS
2 | , dhallArch
3 | ) where
4 |
5 | import Package.C.Triple.Type hiding (arch, os)
6 | import System.Info (arch, os)
7 |
8 | dhallArch :: Arch
9 | dhallArch = case arch of
10 | "x86_64" -> X64
11 | "x86" -> X86
12 | "arm" -> Arm
13 | "aarch64" -> AArch
14 | _ -> error "unrecognized architecture"
15 |
16 | dhallOS :: OS
17 | dhallOS = case os of
18 | "freebsd" -> FreeBSD
19 | "openbsd" -> OpenBSD
20 | "netbsd" -> NetBSD
21 | "solaris" -> Solaris
22 | "dragonfly" -> Dragonfly
23 | "linux" -> Linux
24 | "darwin" -> Darwin
25 | "mingw32" -> Windows
26 | _ -> error "unrecognized OS"
27 |
--------------------------------------------------------------------------------
/src/Package/C/Type/Shared.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE DeriveAnyClass #-}
2 | {-# LANGUAGE DeriveGeneric #-}
3 | {-# LANGUAGE DerivingStrategies #-}
4 |
5 |
6 | module Package.C.Type.Shared ( VersionBound (..)
7 | , Dep (..)
8 | ) where
9 |
10 | import qualified Data.Text as T
11 | import Dhall
12 | import Package.C.Type.Version
13 |
14 | data VersionBound = Lower { lower :: Version }
15 | | Upper { upper :: Version }
16 | | LowerUpper { lower :: Version, upper :: Version }
17 | | NoBound
18 | deriving (Generic, FromDhall)
19 |
20 | data Dep = Dep { name :: T.Text
21 | , bound :: VersionBound
22 | } deriving (Generic, FromDhall)
23 |
--------------------------------------------------------------------------------
/src/Package/C/Logging.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE FlexibleContexts #-}
2 |
3 | module Package.C.Logging ( putNormal
4 | , putDiagnostic
5 | , putLoud
6 | ) where
7 |
8 | import Control.Monad.Reader
9 | import Package.C.Type.Verbosity
10 |
11 | putVerbosity :: (MonadReader Verbosity m, MonadIO m) => Verbosity -> String -> m ()
12 | putVerbosity verb s = do
13 | v <- ask
14 | when (v >= verb)
15 | (liftIO (putStrLn s))
16 |
17 | putNormal :: (MonadReader Verbosity m, MonadIO m) => String -> m ()
18 | putNormal = putVerbosity Normal
19 |
20 | putDiagnostic :: (MonadReader Verbosity m, MonadIO m) => String -> m ()
21 | putDiagnostic = putVerbosity Diagnostic
22 |
23 | putLoud :: (MonadReader Verbosity m, MonadIO m) => String -> m ()
24 | putLoud = putVerbosity Loud
25 |
--------------------------------------------------------------------------------
/test/Spec.hs:
--------------------------------------------------------------------------------
1 | import Package.C
2 | import Test.Hspec
3 | import Test.Hspec.Megaparsec
4 | import Text.Megaparsec
5 |
6 | parseHelper :: String -> TargetTriple -> SpecWith ()
7 | parseHelper str tgt' =
8 | parallel $ it "should work on arm-linux-gnueabihf" $
9 | parse parseTriple "(none)" str
10 | `shouldParse` tgt'
11 |
12 | main :: IO ()
13 | main = hspec $
14 | describe "parseTriple" $ do
15 | parseHelper "arm-linux-gnueabihf" $ TargetTriple Arm Nothing Linux (Just GNUeabihf)
16 | parseHelper "mips64el-linux-gnuabi64" $ TargetTriple Mips64El Nothing Linux (Just GNUabi64)
17 | parseHelper "mips64-linux-gnu" $ TargetTriple Mips64 Nothing Linux (Just GNU)
18 | parseHelper "x86_64-unknown-redox" $ TargetTriple X64 (Just Unknown) Redox Nothing
19 | parseHelper "mipsisa64r6el-linux-gnuabi64" $ TargetTriple MipsIsa64r6El Nothing Linux (Just GNUabi64)
20 |
--------------------------------------------------------------------------------
/bash/tests:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | cabal new-test
6 | cabal new-run cpkg -w ghc-8.2.2 -- check-set './pkgs/pkg-set.dhall'
7 | cabal new-run cpkg -- install feh -vv --pkg-set './pkgs/pkg-set.dhall' --target=arm-linux-gnueabihf
8 | cabal new-run cpkg -- install emacs -vv --pkg-set './pkgs/pkg-set.dhall'
9 | cabal new-run cpkg -- install glibc -vv --pkg-set './pkgs/pkg-set.dhall'
10 | cabal new-run cpkg -- install pHash -vv --pkg-set './pkgs/pkg-set.dhall'
11 | cabal new-run cpkg -- install gnupg -vv --pkg-set './pkgs/pkg-set.dhall'
12 | cabal new-run cpkg -- install qt -vv --pkg-set './pkgs/pkg-set.dhall'
13 | cabal new-run cpkg -- install lapack -vv --pkg-set './pkgs/pkg-set.dhall'
14 | cabal new-run cpkg -- install pdfgrep -vv --pkg-set './pkgs/pkg-set.dhall'
15 | cabal new-run cpkg -- install wget -vv --pkg-set './pkgs/pkg-set.dhall' --target=arm-linux-gnueabihf
16 | cabal new-run cpkg -- install hugs -vv --pkg-set './pkgs/pkg-set.dhall' --target=arm-linux-gnueabihf
17 |
--------------------------------------------------------------------------------
/src/System/Process/Ext.hs:
--------------------------------------------------------------------------------
1 | module System.Process.Ext ( waitProcess
2 | ) where
3 |
4 | import Control.Monad.Reader (ask)
5 | import CPkgPrelude
6 | import Package.C.Monad
7 | import Package.C.Type.Verbosity
8 | import System.Exit (ExitCode (ExitSuccess), exitWith)
9 | import System.Process
10 |
11 | handleExit :: ExitCode -> IO ()
12 | handleExit ExitSuccess = mempty
13 | handleExit x = exitWith x
14 |
15 | verbosityErr :: Verbosity -> StdStream
16 | verbosityErr v | v >= Verbose = Inherit
17 | verbosityErr _ = CreatePipe
18 |
19 | waitProcess :: CreateProcess -> PkgM ()
20 | waitProcess proc' = do
21 | v <- ask
22 | if v >= Loud
23 | then do
24 | (_, _, _, r) <- liftIO $ createProcess (proc' { std_out = Inherit, std_err = Inherit })
25 | liftIO (handleExit =<< waitForProcess r)
26 | else void $ liftIO $ readCreateProcess (proc' { std_err = verbosityErr v }) mempty
27 |
28 |
--------------------------------------------------------------------------------
/bash/builds:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 |
4 | cpkg install gc
5 | cpkg install gc --target=i686-linux-gnu
6 | cpkg install gc --target=x86_64-w64-mingw32
7 | cpkg install gc --target=s390x-linux-gnu
8 | cpkg install gc --target=arm-linux-gnueabihf
9 | cpkg install gc --target=powerpc64-linux-gnu
10 | cpkg install gc --target=powerpc64le-linux-gnu
11 | cpkg install gc --target=powerpc-linux-gnu
12 | cpkg install gc --target=powerpc-linux-gnuspe
13 | cpkg install gc --target=aarch64-linux-gnu
14 | cpkg install gc --target=alpha-linux-gnu
15 | cpkg install gc --target=m68k-linux-gnu
16 | cpkg install gc --target=mips-linux-gnu
17 | cpkg install gc --target=mipsel-linux-gnu
18 | cpkg install gc --target=mips64-linux-gnu
19 | cpkg install gc --target=mips64el-linux-gnu
20 | cpkg install gc --target=sh4-linux-gnu
21 | cpkg install gc --target=arm-linux-gnueabi
22 | cpkg install gc --target=riscv64-linux-gnu
23 | cpkg install gc --target=hppa-linux-gnu
24 | cpkg install gc --target=sparc64-linux-gnu
25 | cpkg install gc --target=hppa64-linux-gnu
26 | cpkg install gc --target=i686-w64-mingw32
27 |
--------------------------------------------------------------------------------
/src/Package/C/Type/Vars.hs:
--------------------------------------------------------------------------------
1 | module Package.C.Type.Vars ( BuildVars (..)
2 | ) where
3 |
4 | import Package.C.Triple.Type
5 |
6 | data BuildVars = BuildVars { installDir :: FilePath
7 | , currentDir :: FilePath
8 | , targetTriple :: Maybe TargetTriple
9 | , isCross :: Bool
10 | , includeDirs :: [ FilePath ]
11 | , preloadLibs :: [ FilePath ]
12 | , shareDirs :: [ FilePath ]
13 | , linkDirs :: [ FilePath ]
14 | , binDirs :: [ FilePath ]
15 | , 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.
16 | , buildArch :: Arch
17 | , static :: Bool
18 | , cpus :: Int
19 | }
20 |
--------------------------------------------------------------------------------
/src/Package/C/Type/Tree.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE DeriveAnyClass #-}
2 | {-# LANGUAGE DeriveFoldable #-}
3 | {-# LANGUAGE DeriveGeneric #-}
4 | {-# LANGUAGE DeriveTraversable #-}
5 | {-# LANGUAGE TypeFamilies #-}
6 |
7 | module Package.C.Type.Tree ( DepTree (..)
8 | , DepTreeF (..)
9 | , asBldDep
10 | ) where
11 |
12 | import Control.Recursion
13 | import GHC.Generics (Generic)
14 |
15 | data DepTree p = DepNode p Bool [DepTree p]
16 | | BldDepNode p [DepTree p]
17 | deriving (Functor, Foldable, Traversable, Generic, Recursive)
18 |
19 | data DepTreeF p x = DepNodeF { self :: p, man :: Bool, deps :: [x] }
20 | | BldDepNodeF { self :: p, deps :: [x] }
21 | deriving (Functor, Foldable, Traversable, Generic)
22 |
23 | type instance Base (DepTree a) = DepTreeF a
24 |
25 | asBldDep :: DepTree p -> DepTree p
26 | asBldDep (DepNode p _ ps) = BldDepNode p (fmap asBldDep ps)
27 | asBldDep (BldDepNode p ps) = BldDepNode p (fmap asBldDep ps)
28 |
--------------------------------------------------------------------------------
/.hlint.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | - functions:
3 | - {name: unsafePerformIO, within: []}
4 | - {name: undefined, within: [Package.C.Db.Register]}
5 | - {name: fromJust, within: []}
6 | - {name: foldl, within: []}
7 | - {name: traceShowId, within: []}
8 | - {name: traceShow, within: []}
9 | - {name: diagnosticDirectory, within: []}
10 |
11 | - ignore: {name: "Avoid lambda using `infix`"}
12 | - ignore: {name: "Use section"}
13 | - ignore: {name: "Redundant lambda"}
14 | - ignore: {name: "Replace case with fromMaybe"}
15 |
16 | - error: {lhs: "f *> pure ()", rhs: "void f", name: "Use void"}
17 | - error: {lhs: "over _1 f x", rhs: "first f x", name: "Use arrows"}
18 | - error: {lhs: "over _2 f x", rhs: "second f x", name: "Use arrows"}
19 | - error: {lhs: "bool x x p", rhs: "x", name: "Redundant bool"}
20 | - error: {lhs: "maybe mempty", rhs: "foldMap", name: "Use foldMap"}
21 | - error: {lhs: "if p then x else pure ()", rhs: "when p x"}
22 | - error: {lhs: "fmap (pure ())", rhs: "void", name: "Use void"}
23 |
24 | - fixity: infixr 3 ***
25 | - fixity: infixr 3 &&&
26 | - fixity: infixr 1 <=<
27 | - fixity: infixr 1 <=*<
28 |
--------------------------------------------------------------------------------
/src/Package/C/Db/Memory.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE FlexibleContexts #-}
2 |
3 | module Package.C.Db.Memory ( strictIndex
4 | , pkgIndex
5 | , globalPkgDir
6 | , memIndex
7 | ) where
8 |
9 | import Control.Monad.State.Class
10 | import CPkgPrelude
11 | import Data.Binary (decode)
12 | import qualified Data.ByteString as BS
13 | import qualified Data.ByteString.Lazy as BSL
14 | import Package.C.Db.Monad
15 | import Package.C.Db.Type
16 |
17 | pkgIndex :: MonadIO m => m FilePath
18 | pkgIndex = (> "index.bin") <$> globalPkgDir
19 |
20 | globalPkgDir :: MonadIO m => m FilePath
21 | globalPkgDir = liftIO (getAppUserDataDirectory "cpkg")
22 |
23 | memIndex :: MonadDb m => m InstallDb
24 | memIndex = get
25 |
26 | strictIndex :: MonadIO m => m InstallDb
27 | strictIndex = do
28 |
29 | indexFile <- pkgIndex
30 | -- Add some proper error handling here
31 | existsIndex <- liftIO (doesFileExist indexFile)
32 |
33 | if existsIndex
34 | then decode . BSL.fromStrict <$> liftIO (BS.readFile indexFile)
35 | else pure mempty
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright Vanessa McHale (c) 2018-2020
2 |
3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4 |
5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 |
7 | 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.
8 |
9 | 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.
10 |
11 | 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.
12 |
--------------------------------------------------------------------------------
/src/Package/C/Db/Type.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE DeriveAnyClass #-}
2 | {-# LANGUAGE DeriveGeneric #-}
3 | {-# LANGUAGE DerivingStrategies #-}
4 | {-# LANGUAGE GeneralizedNewtypeDeriving #-}
5 |
6 | module Package.C.Db.Type ( BuildCfg (..)
7 | , InstallDb (..)
8 | -- * Lenses
9 | , installedPackages
10 | ) where
11 |
12 | import CPkgPrelude
13 | import Data.Semigroup
14 | import qualified Data.Set as S
15 | import qualified Data.Text as T
16 | import Package.C.Type
17 |
18 | -- TODO: we definitely want something different here - it should allow garbage
19 | -- collection, for one
20 | newtype InstallDb = InstallDb { _installedPackages :: S.Set BuildCfg }
21 | deriving newtype (Semigroup, Monoid, Binary)
22 |
23 | installedPackages :: Lens' InstallDb (S.Set BuildCfg)
24 | installedPackages f s = fmap (\x -> s { _installedPackages = x }) (f (_installedPackages s))
25 |
26 | data BuildCfg = BuildCfg { buildName :: String
27 | , buildVersion :: Version
28 | , pinnedBuildDeps :: [(T.Text, Version)]
29 | , pinnedDeps :: [(T.Text, Version)]
30 | , targetArch :: Maybe TargetTriple
31 | , global :: Bool
32 | , configureCmds :: [ Command ]
33 | , buildCmds :: [ Command ]
34 | , installCmds :: [ Command ]
35 | -- , tarball :: FilePath
36 | , manual :: Bool -- ^ Was this package manually installed?
37 | } deriving (Eq, Ord, Generic, Binary, Hashable)
38 |
--------------------------------------------------------------------------------
/src/Package/C/Unpack.hs:
--------------------------------------------------------------------------------
1 | module Package.C.Unpack ( unpackResponse
2 | , Compression (..)
3 | , TarCompress (..)
4 | ) where
5 |
6 | import qualified Codec.Archive as Archive
7 | import Codec.Archive.Zip (ZipOption (..), extractFilesFromArchive, toArchive)
8 | import qualified Codec.Compression.BZip as Bzip
9 | import qualified Codec.Compression.GZip as Gzip
10 | import qualified Codec.Compression.Lzma as Lzma
11 | import qualified Codec.Compression.Zstd.Lazy as Zstd
12 | import qualified Codec.Lzip as Lzip
13 | import Control.Exception (throw)
14 | import qualified Data.ByteString.Lazy as BSL
15 | import System.Directory
16 |
17 | data TarCompress = Gz
18 | | Xz
19 | | Bz2
20 | | Lz
21 | | Zstd
22 | | None
23 |
24 | data Compression = Tar TarCompress
25 | | Zip
26 |
27 |
28 | getCompressor :: TarCompress -> BSL.ByteString -> BSL.ByteString
29 | getCompressor Gz = Gzip.decompress
30 | getCompressor None = id
31 | getCompressor Xz = Lzma.decompress
32 | getCompressor Bz2 = Bzip.decompress
33 | getCompressor Lz = Lzip.decompress
34 | getCompressor Zstd = Zstd.decompress
35 |
36 | archiveResponse :: TarCompress -> FilePath -> BSL.ByteString -> IO ()
37 | archiveResponse compressScheme dirName =
38 | Archive.throwArchiveM . Archive.unpackToDirLazy dirName . getCompressor compressScheme
39 |
40 | zipResponse :: FilePath -> BSL.ByteString -> IO ()
41 | zipResponse dirName response = withCurrentDirectory dirName $ do
42 | let options = OptDestination dirName
43 | extractFilesFromArchive [options] (toArchive response)
44 |
45 | unpackResponse :: Compression -> FilePath -> BSL.ByteString -> IO ()
46 | unpackResponse (Tar tarCmp) fp response = archiveResponse tarCmp fp response
47 | unpackResponse Zip fp response = zipResponse fp response
48 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # cpkg
2 |
3 | ## 0.2.5.0
4 |
5 | * Add `package set:` info to `dhall --version`
6 |
7 | ## 0.2.4.2
8 |
9 | * Support `aarch64`
10 |
11 | ## 0.2.4.1
12 |
13 | * Use `bz2` in place of `bzlib` for now
14 |
15 | ## 0.2.4.0
16 |
17 | * Use [`libarchive`](http://hackage.haskell.org/package/libarchive) exclusively
18 |
19 | ## 0.2.3.8
20 |
21 | * Support `.zst` via [zstd](http://hackage.haskell.org/package/zstd) library
22 | * Pin new Dhall package set
23 |
24 | ## 0.2.3.7
25 |
26 | * Pin package
27 |
28 | ## 0.2.3.6
29 |
30 | * Use `dhall` 1.27.0
31 |
32 | ## 0.2.3.5
33 |
34 | * Use `lzlib` 0.3.0.0
35 |
36 | ## 0.2.3.4
37 |
38 | * Use `libarchive` 2.0.0.0
39 |
40 | ## 0.2.3.3
41 |
42 | * Add `find` subcommand
43 |
44 | ## 0.2.3.2
45 |
46 | * Add `.lz` support
47 |
48 | ## 0.2.3.1
49 |
50 | * Now works with Dhall 1.25.0 on a sufficiently new GHC
51 |
52 | ## 0.2.3.0
53 |
54 | * Add `garbage-collect` subcommand
55 | * Add `uninstall` subcommand
56 | * Add `nuke-cache` subcommand
57 |
58 | ## 0.2.2.0
59 |
60 | * Add `printLdLibFlags` function and add functionality to CLI interface
61 | * `cfg.installDir` is now absolute
62 |
63 | ## 0.2.1.0
64 |
65 | * Add `SymlinkManpage` command
66 |
67 | ## 0.2.0.1
68 |
69 | * Pass `-p0` option to `patch`
70 |
71 | ## 0.2.0.0
72 |
73 | * Support more MIPS architectures
74 |
75 | ## 0.1.3.1
76 |
77 | * Don't install build-tool dependencies globally
78 |
79 | ## 0.1.3.0
80 |
81 | * Add ability to patch libraries
82 |
83 | ## 0.1.2.1
84 |
85 | * Add `--global` flag
86 |
87 | ## 0.1.2.0
88 |
89 | * Export `Dep`
90 |
91 | ## 0.1.1.1
92 |
93 | * Stream using `libarchive` lazily
94 |
95 | ## 0.1.1.0
96 |
97 | * Export `EnvVar`
98 | * Better diagnostic output
99 | * Fix bug where cross dependencies' `bin/` directory was added to `PATH` for
100 | subsequent package builds
101 | * Allow use of `libarchive` for packages that cannot be handled with the `tar`
102 | library
103 |
104 | ## 0.1.0.0
105 |
106 | Initial release
107 |
--------------------------------------------------------------------------------
/src/CPkgPrelude.hs:
--------------------------------------------------------------------------------
1 | module CPkgPrelude ( -- * Base reëxports
2 | Generic
3 | , Natural
4 | , void
5 | , when
6 | , unless
7 | , traverse_
8 | , fold
9 | , toList
10 | , filterM
11 | , forM_
12 | , ($>)
13 | , (<=<)
14 | , (<=*<)
15 | , MonadIO (..)
16 | , Void
17 | -- * Dhall reëxports
18 | , ToDhall
19 | , FromDhall
20 | -- * hashable reëxports
21 | , Hashable
22 | -- * Exports from "Data.Binary"
23 | , Binary
24 | -- prettyprinter reëxports
25 | , Doc
26 | , Pretty (..)
27 | , punctuate
28 | -- * microlens reëxports
29 | , Lens'
30 | , over
31 | -- * Exports from "System.FilePath"
32 | , (>)
33 | -- * Exports from "System.Directory"
34 | , doesFileExist
35 | , removeDirectoryRecursive
36 | , getAppUserDataDirectory
37 | ) where
38 |
39 | import Control.Composition ((<=*<))
40 | import Control.Monad
41 | import Control.Monad.IO.Class (MonadIO (..))
42 | import Data.Binary (Binary)
43 | import Data.Foldable
44 | import Data.Functor (($>))
45 | import Data.Hashable (Hashable)
46 | import Data.Text.Prettyprint.Doc
47 | import Data.Void (Void)
48 | import Dhall (FromDhall, ToDhall)
49 | import GHC.Generics (Generic)
50 | import GHC.Natural (Natural)
51 | import Lens.Micro (Lens', over)
52 | import System.Directory
53 | import System.FilePath ((>))
54 |
--------------------------------------------------------------------------------
/src/Package/C.hs:
--------------------------------------------------------------------------------
1 | module Package.C (
2 | -- * Types
3 | CPkg (..)
4 | , BuildVars (..)
5 | , Version (..)
6 | , Verbosity (..)
7 | , TargetTriple (..)
8 | , Command (..)
9 | , OS (..)
10 | , Arch (..)
11 | , Manufacturer (..)
12 | , ABI (..)
13 | , InstallDb (..)
14 | , BuildCfg (..)
15 | , EnvVar (..)
16 | , MonadDb
17 | , PkgM
18 | , Platform
19 | , Dep (..)
20 | -- * Functions
21 | , buildCPkg
22 | , runPkgM
23 | , globalPkgDir
24 | , printLinkerFlags
25 | , printCompilerFlags
26 | , printPkgConfigPath
27 | , printIncludePath
28 | , printLibPath
29 | , printLdLibPath
30 | , printCabalFlags
31 | , buildByName
32 | , uninstallPkgByName
33 | , garbageCollect
34 | , cleanCache
35 | -- * Dhall functionality
36 | , cPkgDhallToCPkg
37 | , getCPkg
38 | , getPkgs
39 | -- * Packaging
40 | , displayPackageSet
41 | , displayPackage
42 | , allPackages
43 | -- * Parsers
44 | , parseTriple
45 | , parseTripleIO
46 | , parseHostIO
47 | -- * Version
48 | , defaultPackageSetHash
49 | ) where
50 |
51 | import Package.C.Build
52 | import Package.C.Build.Tree
53 | import Package.C.Db.GarbageCollect
54 | import Package.C.Db.Monad
55 | import Package.C.Db.Register
56 | import Package.C.Db.Type
57 | import Package.C.Dhall
58 | import Package.C.Monad
59 | import Package.C.PackageSet
60 | import Package.C.Triple
61 | import Package.C.Type
62 |
--------------------------------------------------------------------------------
/src/Package/C/Error.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE OverloadedStrings #-}
2 |
3 | module Package.C.Error ( printErr
4 | , unrecognized
5 | , indexError
6 | , corruptedDatabase
7 | , unfoundPackage
8 | , parseErr
9 | , notInstalled
10 | , PackageError (..)
11 | ) where
12 |
13 | import CPkgPrelude
14 | import Data.Text.Prettyprint.Doc
15 | import Data.Text.Prettyprint.Doc.Custom
16 | import Data.Text.Prettyprint.Doc.Render.Text
17 | import System.Exit
18 |
19 | data PackageError = Unrecognized String
20 | | IndexError String -- package name
21 | | CorruptedDatabase
22 | | UnfoundPackage -- TODO: this should take the package name as an argument
23 | | NotInstalled String
24 | | ParseFailed String
25 | -- TODO: libarchive error
26 |
27 | instance Pretty PackageError where
28 | pretty (Unrecognized t) = "Error: Unrecognized archive format when unpacking" <#> hang 2 (pretty t) <> hardline
29 | pretty (IndexError str) = "Error: Package" <+> pretty str <+> "not found in your indices. Try 'cpkg install" <+> pretty str <> "'." <> hardline
30 | pretty CorruptedDatabase = "Error: Package database corrupted. Please try 'cpkg nuke'" <> hardline
31 | pretty UnfoundPackage = "Error: Package not found" <> hardline
32 | pretty (ParseFailed str) = "Parse error:" <+> pretty str
33 | pretty (NotInstalled pkg) = "Package" <+> pretty pkg <+> "is not installed, so not removed." <> hardline
34 |
35 | printErr :: MonadIO m => PackageError -> m a
36 | printErr e = liftIO (putDoc (pretty e) *> exitFailure)
37 |
38 | notInstalled :: MonadIO m => String -> m a
39 | notInstalled = printErr . NotInstalled
40 |
41 | unrecognized :: MonadIO m => String -> m a
42 | unrecognized = printErr . Unrecognized
43 |
44 | indexError :: MonadIO m => String -> m a
45 | indexError = printErr . IndexError
46 |
47 | corruptedDatabase :: MonadIO m => m a
48 | corruptedDatabase = printErr CorruptedDatabase
49 |
50 | unfoundPackage :: MonadIO m => m a
51 | unfoundPackage = printErr UnfoundPackage
52 |
53 | parseErr :: MonadIO m => String -> m a
54 | parseErr = printErr . ParseFailed
55 |
--------------------------------------------------------------------------------
/pkgs/patches/intltool.patch:
--------------------------------------------------------------------------------
1 | --- intltool-update.in 2015-03-08 20:39:54.000000000 -0500
2 | +++ intltool-update.in 2019-06-19 20:58:02.349782444 -0500
3 | @@ -1062,13 +1062,13 @@
4 | }
5 | }
6 |
7 | - if ($str =~ /^(.*)\${?([A-Z_]+)}?(.*)$/)
8 | + if ($str =~ /^(.*)\$\{?([A-Z_]+)}?(.*)$/)
9 | {
10 | my $rest = $3;
11 | my $untouched = $1;
12 | my $sub = "";
13 | # Ignore recursive definitions of variables
14 | - $sub = $varhash{$2} if defined $varhash{$2} and $varhash{$2} !~ /\${?$2}?/;
15 | + $sub = $varhash{$2} if defined $varhash{$2} and $varhash{$2} !~ /\$\{?$2}?/;
16 |
17 | return SubstituteVariable ("$untouched$sub$rest");
18 | }
19 | @@ -1190,10 +1190,10 @@
20 | $name =~ s/\(+$//g;
21 | $version =~ s/\(+$//g;
22 |
23 | - $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/);
24 | - $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/);
25 | - $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/);
26 | - $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/);
27 | + $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\$\{?AC_PACKAGE_NAME}?/);
28 | + $varhash{"PACKAGE"} = $name if (not $name =~ /\$\{?PACKAGE}?/);
29 | + $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\$\{?AC_PACKAGE_VERSION}?/);
30 | + $varhash{"VERSION"} = $version if (not $name =~ /\$\{?VERSION}?/);
31 | }
32 |
33 | if ($conf_source =~ /^AC_INIT\(([^,\)]+),([^,\)]+)[,]?([^,\)]+)?/m)
34 | @@ -1219,11 +1219,11 @@
35 | $version =~ s/\(+$//g;
36 | $bugurl =~ s/\(+$//g if (defined $bugurl);
37 |
38 | - $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/);
39 | - $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/);
40 | - $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/);
41 | - $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/);
42 | - $varhash{"PACKAGE_BUGREPORT"} = $bugurl if (defined $bugurl and not $bugurl =~ /\${?\w+}?/);
43 | + $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\$\{?AC_PACKAGE_NAME}?/);
44 | + $varhash{"PACKAGE"} = $name if (not $name =~ /\$\{?PACKAGE}?/);
45 | + $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\$\{?AC_PACKAGE_VERSION}?/);
46 | + $varhash{"VERSION"} = $version if (not $name =~ /\$\{?VERSION}?/);
47 | + $varhash{"PACKAGE_BUGREPORT"} = $bugurl if (defined $bugurl and not $bugurl =~ /\$\{?\w+}?/);
48 | }
49 |
50 | # \s makes this not work, why?
51 |
--------------------------------------------------------------------------------
/dhall/cpkg-types.dhall:
--------------------------------------------------------------------------------
1 | let OS =
2 | < FreeBSD
3 | | OpenBSD
4 | | NetBSD
5 | | Solaris
6 | | Dragonfly
7 | | Linux
8 | | Darwin
9 | | Windows
10 | | Redox
11 | | Haiku
12 | | IOS
13 | | AIX
14 | | Hurd
15 | | Android
16 | | NoOs
17 | >
18 |
19 | let Arch =
20 | < X64
21 | | AArch
22 | | Arm
23 | | RISCV64
24 | | PowerPC
25 | | PowerPC64
26 | | PowerPC64le
27 | | Sparc64
28 | | S390x
29 | | Alpha
30 | | M68k
31 | | Mips
32 | | MipsEl
33 | | Mips64
34 | | Mips64El
35 | | X86
36 | | SH4
37 | | HPPA
38 | | HPPA64
39 | | MipsIsa32r6El
40 | | MipsIsa32r6
41 | | MipsIsa64r6El
42 | | MipsIsa64r6
43 | >
44 |
45 | let Manufacturer = < Unknown | Apple | IBM | PC >
46 |
47 | let ABI = < GNU | GNUabi64 | GNUeabi | GNUeabihf | GNUspe | MinGw >
48 |
49 | let TargetTriple =
50 | { arch : Arch
51 | , manufacturer : Optional Manufacturer
52 | , os : OS
53 | , abi : Optional ABI
54 | }
55 |
56 | let BuildVars =
57 | { installDir : Text
58 | , currentDir : Text
59 | , targetTriple : Optional TargetTriple
60 | , isCross : Bool
61 | , includeDirs : List Text
62 | , preloadLibs : List Text
63 | , shareDirs : List Text
64 | , linkDirs : List Text
65 | , binDirs : List Text
66 | , buildOS : OS
67 | , buildArch : Arch
68 | , static : Bool
69 | , cpus : Natural
70 | }
71 |
72 | let VersionBound =
73 | < Lower : { lower : List Natural }
74 | | Upper : { upper : List Natural }
75 | | LowerUpper : { lower : List Natural, upper : List Natural }
76 | | NoBound
77 | >
78 |
79 | let Dep = { name : Text, bound : VersionBound }
80 |
81 | let EnvVar = { var : Text, value : Text }
82 |
83 | let Proc =
84 | { program : Text
85 | , arguments : List Text
86 | , environment : Optional (List EnvVar)
87 | , procDir : Optional Text
88 | }
89 |
90 | let Command =
91 | < CreateDirectory : { dir : Text }
92 | | MakeExecutable : { file : Text }
93 | | Call : Proc
94 | | SymlinkBinary : { file : Text }
95 | | SymlinkManpage : { file : Text, section : Natural }
96 | | Symlink : { tgt : Text, linkName : Text }
97 | | Write : { file : Text, contents : Text }
98 | | CopyFile : { src : Text, dest : Text }
99 | | Patch : { patchContents : Text }
100 | >
101 |
102 | in { OS
103 | , BuildVars
104 | , VersionBound
105 | , Dep
106 | , Arch
107 | , Manufacturer
108 | , ABI
109 | , TargetTriple
110 | , Command
111 | , EnvVar
112 | , Proc
113 | }
114 |
--------------------------------------------------------------------------------
/src/Package/C/Fetch.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE OverloadedStrings #-}
2 |
3 | module Package.C.Fetch ( fetchUrl
4 | ) where
5 |
6 | import CPkgPrelude
7 | import qualified Data.ByteString.Lazy as BSL
8 | import Data.List (isSuffixOf)
9 | import Data.Maybe (fromJust)
10 | import Network.HTTP.Client
11 | import Network.HTTP.Client.TLS (tlsManagerSettings)
12 | import Network.URI
13 | import Package.C.Db.Register
14 | import Package.C.Error
15 | import Package.C.Logging
16 | import Package.C.Monad
17 | import Package.C.Unpack
18 | import System.Directory (createDirectoryIfMissing)
19 | import System.FilePath (takeFileName)
20 |
21 | urlToCompression :: MonadIO m => String -> m Compression
22 | urlToCompression s | ".tar.gz" `isSuffixOf` s || ".tgz" `isSuffixOf` s = pure $ Tar Gz
23 | | ".tar.xz" `isSuffixOf` s || ".txz" `isSuffixOf` s = pure $ Tar Xz
24 | | ".tar.bz2" `isSuffixOf` s = pure $ Tar Bz2
25 | | ".tar.lz" `isSuffixOf` s = pure $ Tar Lz
26 | | ".tar.zst" `isSuffixOf` s = pure $ Tar Zstd
27 | | ".tar" `isSuffixOf` s = pure $ Tar None
28 | | ".zip" `isSuffixOf` s = pure Zip
29 | | otherwise = unrecognized s
30 |
31 | asFilename :: String -> Maybe String
32 | asFilename = fmap (takeFileName . uriPath) . parseURI
33 |
34 | cacheDir :: MonadIO m => m FilePath
35 | cacheDir = (> "cache") <$> globalPkgDir
36 |
37 | fetchUrl :: String -- ^ URL
38 | -> String -- ^ Package name
39 | -> FilePath -- ^ Directory to unpack to
40 | -> PkgM ()
41 | fetchUrl url name dirName = do
42 |
43 | let tarballName = fromJust (asFilename url)
44 | tarballDir <- (> tarballName) <$> cacheDir
45 | shouldDownload <- not <$> liftIO (doesFileExist tarballDir)
46 |
47 | compression <- urlToCompression url
48 |
49 | response <-
50 | if shouldDownload
51 | then do
52 | putNormal ("Downloading " ++ name)
53 |
54 | putLoud ("from URL " ++ url)
55 |
56 | manager <- liftIO $ newManager tlsManagerSettings
57 | initialRequest <- liftIO $ parseRequest url
58 | liftIO $ responseBody <$> httpLbs (initialRequest { method = "GET" }) manager
59 | else do
60 | putDiagnostic ("Using cached tarball at " ++ tarballDir)
61 | liftIO $ BSL.readFile tarballDir
62 |
63 | cacheDirExists <- liftIO (doesFileExist =<< cacheDir)
64 | unless cacheDirExists
65 | (liftIO $ createDirectoryIfMissing True =<< cacheDir)
66 |
67 | when shouldDownload $ do
68 | -- TODO: should cache/compress to .tar.xz?
69 | putLoud ("Caching " ++ tarballName)
70 | liftIO $ BSL.writeFile tarballDir response
71 |
72 | putNormal ("Unpacking " ++ name)
73 |
74 | liftIO $ unpackResponse compression dirName response
75 |
--------------------------------------------------------------------------------
/src/Package/C/Triple/Parse.hs:
--------------------------------------------------------------------------------
1 | module Package.C.Triple.Parse ( parseTriple
2 | , parseTripleIO
3 | ) where
4 |
5 | import CPkgPrelude
6 | import Package.C.Error
7 | import Package.C.Triple.Type
8 | import Text.Megaparsec
9 | import Text.Megaparsec.Char
10 |
11 | type Parser = Parsec Void String
12 |
13 | parseTripleIO :: MonadIO m => String -> m TargetTriple
14 | parseTripleIO = parseIO parseTriple
15 |
16 | parseIO :: MonadIO m => Parser a -> String -> m a
17 | parseIO p str =
18 | case parse p "(none)" str of
19 | Right x -> pure x
20 | Left err -> parseErr (errorBundlePretty err)
21 |
22 | parseTriple :: Parser TargetTriple
23 | parseTriple = TargetTriple
24 | <$> parseArch
25 | <*> optional (try (char '-' *> parseManufacturer))
26 | <*> (char '-' *> parseOS)
27 | <*> optional (char '-' *> parseABI)
28 |
29 | tryString :: String -> Parser String
30 | tryString = try . string
31 |
32 | parseArch :: Parser Arch
33 | parseArch =
34 | (tryString "x86_64" $> X64)
35 | <|> (tryString "armv7l" $> Arm)
36 | <|> (tryString "arm" $> Arm)
37 | <|> (tryString "aarch64" $> AArch)
38 | <|> (tryString "riscv64" $> RISCV64)
39 | <|> (tryString "powerpc64le" $> PowerPC64le)
40 | <|> (tryString "powerpc64" $> PowerPC64)
41 | <|> (tryString "powerpc" $> PowerPC)
42 | <|> (tryString "sparc64" $> Sparc64)
43 | <|> (tryString "s390x" $> S390x)
44 | <|> (tryString "alpha" $> Alpha)
45 | <|> (tryString "m68k" $> M68k)
46 | <|> (tryString "mipsisa32r6el" $> MipsIsa32r6El)
47 | <|> (tryString "mipsisa32r6" $> MipsIsa32r6)
48 | <|> (tryString "mipsisa64r6el" $> MipsIsa64r6El)
49 | <|> (tryString "mipsisa64r6" $> MipsIsa64r6)
50 | <|> (tryString "mips64el" $> Mips64El)
51 | <|> (tryString "mips64" $> Mips64)
52 | <|> (tryString "mipsel" $> MipsEl)
53 | <|> (tryString "mips" $> Mips)
54 | <|> (tryString "i686" $> X86)
55 | <|> (tryString "sh4" $> SH4)
56 | <|> (tryString "hppa64" $> HPPA64)
57 | <|> (tryString "hppa" $> HPPA)
58 |
59 | parseManufacturer :: Parser Manufacturer
60 | parseManufacturer =
61 | (tryString "unknown" $> Unknown)
62 | <|> (tryString "apple" $> Apple)
63 | <|> (tryString "ibm" $> IBM)
64 | <|> (tryString "pc" $> PC)
65 |
66 | parseOS :: Parser OS
67 | parseOS =
68 | (tryString "darwin" $> Darwin)
69 | <|> (tryString "dragonfly" $> Dragonfly)
70 | <|> (tryString "freebsd" $> FreeBSD)
71 | <|> (tryString "linux" $> Linux)
72 | <|> (tryString "openbsd" $> OpenBSD)
73 | <|> (tryString "netbsd" $> NetBSD)
74 | <|> (tryString "solaris" $> Solaris)
75 | <|> (tryString "w64" $> Windows)
76 | <|> (tryString "redox" $> Redox)
77 | <|> (tryString "haiku" $> Haiku)
78 | <|> (tryString "ios" $> IOS)
79 | <|> (tryString "aix" $> AIX)
80 | <|> (tryString "hurd" $> Hurd)
81 | <|> (tryString "android" $> Android)
82 | <|> (tryString "none" $> NoOs)
83 |
84 | parseABI :: Parser ABI
85 | parseABI =
86 | (tryString "gnueabihf" $> GNUeabihf)
87 | <|> (tryString "gnuabi64" $> GNUabi64)
88 | <|> (tryString "gnueabi" $> GNUeabi)
89 | <|> (tryString "gnuspe" $> GNUspe)
90 | <|> (tryString "gnu" $> GNU)
91 | <|> (tryString "mingw32" $> MinGw)
92 |
--------------------------------------------------------------------------------
/src/Package/C/Db/GarbageCollect.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE FlexibleContexts #-}
2 |
3 | module Package.C.Db.GarbageCollect ( cleanSymlinks
4 | , cleanCache
5 | , garbageCollect
6 | ) where
7 |
8 | import Control.Monad.Reader (MonadReader)
9 | import CPkgPrelude
10 | import qualified Data.Set as S
11 | import qualified Data.Text as T
12 | import Package.C.Db.Memory (globalPkgDir)
13 | import Package.C.Db.Monad (MonadDb)
14 | import Package.C.Db.Register
15 | import Package.C.Db.Type
16 | import Package.C.Logging (putDiagnostic)
17 | import Package.C.Type (TargetTriple, Verbosity)
18 | import System.Directory (doesDirectoryExist, doesFileExist, getSymbolicLinkTarget, listDirectory, removeDirectoryRecursive, removeFile)
19 | import System.FilePath ((>))
20 |
21 | getTransitiveDepsByName :: (MonadIO m, MonadDb m) => String -> Maybe TargetTriple -> m (S.Set BuildCfg)
22 | getTransitiveDepsByName = getTransitiveDeps <=*< lookupOrFail
23 |
24 | garbageCollect :: (MonadIO m, MonadDb m, MonadReader Verbosity m)
25 | => m ()
26 | garbageCollect = garbageCollectPkgs *> cleanSymlinks
27 |
28 | -- TODO: garbage collect old packages as well, and things which are broken b/c
29 | -- their dependencies are gone
30 | --
31 | -- | @since 0.2.3.0
32 | garbageCollectPkgs :: (MonadIO m, MonadDb m, MonadReader Verbosity m)
33 | => m ()
34 | garbageCollectPkgs = do
35 | allPkgs <- installedDb
36 | let manuals = (toList . S.filter manual) allPkgs
37 | putDiagnostic ("Manually installed packages: " ++ show (buildName <$> manuals))
38 | allDeps <- S.unions <$> traverse getTransitiveDeps manuals
39 | let redundant = allPkgs S.\\ allDeps
40 | putDiagnostic ("Redundant packages: " ++ show (buildName <$> toList redundant))
41 | traverse_ uninstallPkg redundant
42 |
43 | getTransitiveDeps :: (MonadIO m, MonadDb m) => BuildCfg -> m (S.Set BuildCfg)
44 | getTransitiveDeps cfg = do
45 | let names = fst <$> pinnedDeps cfg
46 | host = targetArch cfg
47 | next <- traverse (\n -> getTransitiveDepsByName n host) (T.unpack <$> names)
48 | pure $ S.insert cfg (S.unions next)
49 |
50 | -- | @since 0.2.3.0
51 | cleanCache :: MonadIO m => m ()
52 | cleanCache = liftIO $ do
53 | ccDir <- (> "cache") <$> globalPkgDir
54 | exists <- doesDirectoryExist ccDir
55 | when exists $
56 | removeDirectoryRecursive ccDir
57 |
58 | cleanSymlinks :: (MonadReader Verbosity m, MonadIO m) => m ()
59 | cleanSymlinks = do
60 | pkDir <- liftIO globalPkgDir
61 | let binDir = pkDir > "bin"
62 | manDir = pkDir > "share" > "man"
63 | man1Dir = manDir > "man1"
64 | man3Dir = manDir > "man3"
65 | traverse_ cleanDir
66 | [binDir, man1Dir, man3Dir]
67 |
68 |
69 | cleanDir :: (MonadReader Verbosity m, MonadIO m) => FilePath -> m ()
70 | cleanDir dir = do
71 | exists <- liftIO $ doesDirectoryExist dir
72 | when exists $ do
73 | links <- liftIO $ listDirectory dir
74 | forM_ links $ \link -> do
75 | let linkAbs = dir > link
76 | brk <- liftIO $ isBroken linkAbs
77 | when brk $
78 | putDiagnostic ("Removing link " ++ linkAbs ++ "...") *>
79 | liftIO (removeFile linkAbs)
80 |
81 | isBroken :: FilePath -> IO Bool
82 | isBroken = (fmap not . doesFileExist) <=< getSymbolicLinkTarget
83 |
84 | -- getSymbolicLinkTarget
85 |
--------------------------------------------------------------------------------
/src/Package/C/Dhall/Type.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE DeriveAnyClass #-}
2 | {-# LANGUAGE DeriveGeneric #-}
3 | {-# LANGUAGE OverloadedStrings #-}
4 |
5 | module Package.C.Dhall.Type ( CPkg (..)
6 | , BuildVars (..)
7 | , EnvVar (..)
8 | , Command (..)
9 | ) where
10 |
11 | import qualified Data.Text as T
12 | import Data.Text.Prettyprint.Doc
13 | import Data.Text.Prettyprint.Doc.Custom
14 | import Dhall
15 | import GHC.Natural (Natural)
16 | import Package.C.Triple.Type
17 | import Package.C.Type.Shared
18 | import Package.C.Type.Version
19 |
20 | data BuildVars = BuildVars { installDir :: T.Text
21 | , currentDir :: T.Text
22 | , targetTriple :: Maybe TargetTriple
23 | , isCross :: Bool
24 | , includeDirs :: [ T.Text ]
25 | , preloadLibs :: [ T.Text ]
26 | -- TODO: nameToLinkDir function??
27 | , shareDirs :: [ T.Text ]
28 | , linkDirs :: [ T.Text ]
29 | , binDirs :: [ T.Text ]
30 | , buildOS :: OS
31 | , buildArch :: Arch
32 | , static :: Bool
33 | , cpus :: Natural
34 | } deriving (Generic, ToDhall)
35 |
36 | data EnvVar = EnvVar { var :: T.Text, value :: T.Text }
37 | deriving (Generic, FromDhall)
38 |
39 | data Command = CreateDirectory { dir :: T.Text }
40 | | MakeExecutable { file :: T.Text }
41 | | Call { program :: T.Text
42 | , arguments :: [T.Text]
43 | , environment :: Maybe [EnvVar]
44 | , procDir :: Maybe T.Text
45 | }
46 | | SymlinkBinary { file :: T.Text }
47 | | SymlinkManpage { file :: T.Text, section :: Natural }
48 | | Symlink { tgt :: T.Text, linkName :: T.Text }
49 | | Write { contents :: T.Text, file :: T.Text }
50 | | CopyFile { src :: T.Text, dest :: T.Text }
51 | | Patch { patchContents :: T.Text }
52 | deriving (Generic, FromDhall)
53 |
54 | data CPkg = CPkg { pkgName :: T.Text
55 | , pkgVersion :: [ Natural ]
56 | , pkgUrl :: T.Text
57 | , pkgSubdir :: T.Text
58 | , pkgBuildDeps :: [ Dep ] -- TODO: depend on target?
59 | , pkgDeps :: [ Dep ]
60 | , configureCommand :: BuildVars -> [ Command ]
61 | , buildCommand :: BuildVars -> [ Command ]
62 | , installCommand :: BuildVars -> [ Command ]
63 | -- TODO: add "description" field for printing
64 | -- TODO: add "test" command for e.g. `make check`
65 | } deriving (Generic, FromDhall)
66 |
67 | preDeps :: Doc a -> [ Dep ] -> Doc a
68 | preDeps _ [] = ""
69 | preDeps dep ds = hardline <> dep <+> hsep (punctuate "," (pretty . name <$> ds))
70 |
71 | prettyDeps :: [ Dep ] -> Doc a
72 | prettyDeps = preDeps "dependencies:"
73 |
74 | prettyBldDeps :: [ Dep ] -> Doc a
75 | prettyBldDeps = preDeps "build dependencies:"
76 |
77 | instance Pretty CPkg where
78 | pretty (CPkg nam v url _ bds ds _ _ _) = pretty nam <##> indent 4 ("url:" <+> pretty url <##> "version:" <+> pretty (Version v) <> prettyDeps ds <> prettyBldDeps bds)
79 |
--------------------------------------------------------------------------------
/src/Package/C/PackageSet.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-}
2 | {-# LANGUAGE OverloadedStrings #-}
3 |
4 | module Package.C.PackageSet ( PackageSet (..)
5 | , PackId
6 | , pkgsM
7 | , displayPackageSet
8 | , displayPackage
9 | , defaultPackageSetHash
10 | ) where
11 |
12 | import CPkgPrelude
13 | import Data.Containers.ListUtils
14 | import Data.List (find, intersperse)
15 | import qualified Data.Map as M
16 | import qualified Data.Text as T
17 | import Data.Text.Prettyprint.Doc
18 | import Data.Text.Prettyprint.Doc.Custom
19 | import Data.Text.Prettyprint.Doc.Render.Text
20 | import Dhall hiding (maybe)
21 | import qualified Package.C.Dhall.Type as Dhall
22 | import Package.C.Error
23 | import Package.C.Type
24 | import Package.C.Type.Tree
25 |
26 | defaultPackageSetHash :: T.Text
27 | defaultPackageSetHash = "sha256:172035e1adc2b2f0e4035e943125f6c7afb53e2e0055313709d0c4208eb83850"
28 |
29 | defaultPackageSetDhall :: Maybe String -> IO PackageSetDhall
30 | defaultPackageSetDhall (Just pkSet) = input auto (T.pack pkSet)
31 | defaultPackageSetDhall Nothing = input auto ("https://raw.githubusercontent.com/vmchale/cpkg/a82629bc65449b66c0ab337faaeb0d12096675f6/pkgs/pkg-set.dhall " <> defaultPackageSetHash)
32 |
33 |
34 | displayPackageSet :: Maybe String -> IO ()
35 | displayPackageSet = putDoc . pretty <=< defaultPackageSetDhall
36 |
37 | displayPackage :: String -> IO ()
38 | displayPackage str = do
39 | pk <- find (\ps -> T.unpack (Dhall.pkgName ps) == str) . listPackages <$> defaultPackageSetDhall Nothing
40 | case pk of
41 | Just p -> putDoc (pretty p <> hardline)
42 | Nothing -> unfoundPackage
43 |
44 | newtype PackageSetDhall = PackageSetDhall { listPackages :: [ Dhall.CPkg ] }
45 | deriving FromDhall
46 |
47 | instance Pretty PackageSetDhall where
48 | pretty (PackageSetDhall set) = vdisplay (intersperse hardline (pretty <$> set)) <> hardline
49 |
50 | newtype PackageSet = PackageSet (M.Map T.Text CPkg)
51 |
52 | type PackId = T.Text
53 |
54 | packageSetDhallToPackageSet :: PackageSetDhall -> PackageSet
55 | packageSetDhallToPackageSet (PackageSetDhall pkgs'') =
56 | let names = Dhall.pkgName <$> pkgs''
57 | pkgs' = cPkgDhallToCPkg <$> pkgs''
58 |
59 | in PackageSet $ M.fromList (zip names pkgs')
60 |
61 | getDeps :: PackId -> Bool -> PackageSet -> Maybe (DepTree PackId)
62 | getDeps pkgName' usr set@(PackageSet ps) = do
63 | cpkg <- M.lookup pkgName' ps
64 | let depNames = name <$> pkgDeps cpkg
65 | bldDepNames = name <$> pkgBuildDeps cpkg
66 | ds = nubOrd depNames
67 | bds = nubOrd bldDepNames
68 | nextDeps <- traverse (\p -> getDeps p False set) ds
69 | nextBldDeps <- traverse (\p -> asBldDep <$> getDeps p False set) bds
70 | pure $ DepNode pkgName' usr (nextDeps ++ nextBldDeps)
71 |
72 | -- TODO: use dfsForest but check for cycles
73 | pkgPlan :: PackId -> PackageSet -> Maybe (DepTree PackId)
74 | pkgPlan pkId = getDeps pkId True -- manually installed
75 |
76 | pkgs :: PackId -> PackageSet -> Maybe (DepTree CPkg)
77 | pkgs pkId set@(PackageSet pset) = do
78 | plan <- pkgPlan pkId set
79 | traverse (`M.lookup` pset) plan
80 |
81 | pkgsM :: PackId -> Maybe String -> IO (DepTree CPkg)
82 | pkgsM pkId pkSet = do
83 | pks <- pkgs pkId . packageSetDhallToPackageSet <$> defaultPackageSetDhall pkSet
84 | maybe unfoundPackage pure pks
85 |
--------------------------------------------------------------------------------
/pkgs/patches/pHash.patch:
--------------------------------------------------------------------------------
1 | --- src/cimgffmpeg.cpp 2019-06-22 20:18:05.632517868 -0500
2 | +++ src/cimgffmpeg.cpp 2019-06-22 20:18:45.569003435 -0500
3 | @@ -100,12 +100,12 @@
4 | AVFrame *pFrame;
5 |
6 | // Allocate video frame
7 | - pFrame=avcodec_alloc_frame();
8 | + pFrame=av_frame_alloc();
9 | if (pFrame==NULL)
10 | return -1;
11 |
12 | // Allocate an AVFrame structure
13 | - AVFrame *pConvertedFrame = avcodec_alloc_frame();
14 | + AVFrame *pConvertedFrame = av_frame_alloc();
15 | if(pConvertedFrame==NULL)
16 | return -1;
17 |
18 | @@ -254,10 +254,10 @@
19 | AVFrame *pFrame;
20 |
21 | // Allocate video frame
22 | - pFrame=avcodec_alloc_frame();
23 | + pFrame=av_frame_alloc();
24 |
25 | // Allocate an AVFrame structure
26 | - AVFrame *pConvertedFrame = avcodec_alloc_frame();
27 | + AVFrame *pConvertedFrame = av_frame_alloc();
28 | if(pConvertedFrame==NULL){
29 | return -1;
30 | }
31 | --- configure.ac 2019-06-22 21:22:10.582842002 -0500
32 | +++ configure.ac 2019-06-22 21:21:48.962982961 -0500
33 | @@ -122,7 +122,7 @@
34 | AC_DEFUN([AC_CHECK_FFMPEG],
35 | [
36 | AC_MSG_CHECKING([whether FFmpeg is present])
37 | -AC_CHECK_LIB([avcodec], [avcodec_alloc_frame], [], [AC_MSG_ERROR([
38 | +AC_CHECK_LIB([avutil], [av_frame_alloc], [], [AC_MSG_ERROR([
39 |
40 | *** libavcodec not found.
41 | You need FFmpeg. Get it at ])])
42 | --- src/pHash.h 2019-06-23 11:31:15.678771295 -0500
43 | +++ src/pHash.h 2019-06-23 11:31:31.754816275 -0500
44 | @@ -47,6 +47,8 @@
45 | #if defined(HAVE_IMAGE_HASH) || defined(HAVE_VIDEO_HASH)
46 | #define cimg_debug 0
47 | #define cimg_display 0
48 | +#define cimg_use_png
49 | +#define cimg_use_jpeg
50 | #include "CImg.h"
51 | using namespace cimg_library;
52 | #endif
53 | --- src/cimgffmpeg.cpp 2019-06-22 21:50:15.060403190 -0500
54 | +++ src/cimgffmpeg.cpp 2019-06-22 21:56:50.839827371 -0500
55 | @@ -39,11 +39,11 @@
56 | int ReadFrames(VFInfo *st_info, CImgList *pFrameList, unsigned int low_index, unsigned int hi_index)
57 | {
58 | //target pixel format
59 | - PixelFormat ffmpeg_pixfmt;
60 | + AVPixelFormat ffmpeg_pixfmt;
61 | if (st_info->pixelformat == 0)
62 | - ffmpeg_pixfmt = PIX_FMT_GRAY8;
63 | + ffmpeg_pixfmt = AV_PIX_FMT_GRAY8;
64 | else
65 | - ffmpeg_pixfmt = PIX_FMT_RGB24;
66 | + ffmpeg_pixfmt = AV_PIX_FMT_RGB24;
67 |
68 | st_info->next_index = low_index;
69 |
70 | @@ -123,7 +123,7 @@
71 | int size = 0;
72 |
73 |
74 | - int channels = ffmpeg_pixfmt == PIX_FMT_GRAY8 ? 1 : 3;
75 | + int channels = ffmpeg_pixfmt == AV_PIX_FMT_GRAY8 ? 1 : 3;
76 |
77 | AVPacket packet;
78 | int result = 1;
79 | @@ -189,11 +189,11 @@
80 |
81 | int NextFrames(VFInfo *st_info, CImgList *pFrameList)
82 | {
83 | - PixelFormat ffmpeg_pixfmt;
84 | + AVPixelFormat ffmpeg_pixfmt;
85 | if (st_info->pixelformat == 0)
86 | - ffmpeg_pixfmt = PIX_FMT_GRAY8;
87 | + ffmpeg_pixfmt = AV_PIX_FMT_GRAY8;
88 | else
89 | - ffmpeg_pixfmt = PIX_FMT_RGB24;
90 | + ffmpeg_pixfmt = AV_PIX_FMT_RGB24;
91 |
92 | if (st_info->pFormatCtx == NULL)
93 | {
94 | @@ -287,7 +287,7 @@
95 | break;
96 | if(packet.stream_index == st_info->videoStream) {
97 |
98 | - int channels = ffmpeg_pixfmt == PIX_FMT_GRAY8 ? 1 : 3;
99 | + int channels = ffmpeg_pixfmt == AV_PIX_FMT_GRAY8 ? 1 : 3;
100 | AVPacket avpkt;
101 | av_init_packet(&avpkt);
102 | avpkt.data = packet.data;
103 | --- src/cimgffmpeg.h 2019-06-23 11:47:59.046307628 -0500
104 | +++ src/cimgffmpeg.h 2019-06-23 11:32:14.754956444 -0500
105 | @@ -30,6 +30,8 @@
106 | #define cimg_display 0
107 | #define cimg_debug 0
108 |
109 | +#define cimg_use_png
110 | +#define cimg_use_jpeg
111 | #include "CImg.h"
112 |
113 | #define __STDC_CONSTANT_MACROS
114 |
--------------------------------------------------------------------------------
/src/Package/C/Type.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE DeriveAnyClass #-}
2 | {-# LANGUAGE DeriveGeneric #-}
3 |
4 | module Package.C.Type ( CPkg (..)
5 | , BuildVars (..)
6 | , Verbosity (..)
7 | , EnvVar (..)
8 | , Command (..)
9 | , Dep (..)
10 | , Version (..)
11 | , OS (..)
12 | , TargetTriple (..)
13 | -- * Helper functions
14 | , cPkgDhallToCPkg
15 | , showVersion
16 | ) where
17 |
18 | import CPkgPrelude
19 | import qualified Data.Text as T
20 | import GHC.Generics (Generic)
21 | import qualified Package.C.Dhall.Type as Dhall
22 | import Package.C.Triple.Type
23 | import Package.C.Type.Shared
24 | import Package.C.Type.Vars
25 | import Package.C.Type.Verbosity
26 | import Package.C.Type.Version
27 |
28 | data EnvVar = EnvVar { var :: String, value :: String }
29 | deriving (Eq, Ord, Generic, Binary, Hashable)
30 |
31 | data Command = CreateDirectory { dir :: String }
32 | | MakeExecutable { file :: String }
33 | | Call { program :: String
34 | , arguments :: [String]
35 | , environment :: Maybe [EnvVar]
36 | , procDir :: Maybe String
37 | }
38 | | SymlinkBinary { file :: String }
39 | | SymlinkManpage { file :: String, section :: Int }
40 | | Symlink { tgt :: String, linkName :: String }
41 | | Write { contents :: T.Text, file :: FilePath }
42 | | CopyFile { src :: FilePath, dest :: FilePath }
43 | | Patch { patchContents :: T.Text }
44 | deriving (Eq, Ord, Generic, Binary, Hashable)
45 |
46 | -- TODO: build script should take OS as an argument?
47 | -- That way we can use make/gmake where we want it
48 | data CPkg = CPkg { pkgName :: String
49 | , pkgVersion :: Version
50 | , pkgUrl :: String
51 | , pkgSubdir :: String
52 | , pkgBuildDeps :: [ Dep ]
53 | , pkgDeps :: [ Dep ]
54 | , configureCommand :: BuildVars -> [ Command ]
55 | , buildCommand :: BuildVars -> [ Command ]
56 | , installCommand :: BuildVars -> [ Command ]
57 | }
58 |
59 | envVarDhallToEnvVar :: Dhall.EnvVar -> EnvVar
60 | envVarDhallToEnvVar (Dhall.EnvVar ev x) = EnvVar (T.unpack ev) (T.unpack x)
61 |
62 | commandDhallToCommand :: Dhall.Command -> Command
63 | commandDhallToCommand (Dhall.CreateDirectory d) = CreateDirectory (T.unpack d)
64 | commandDhallToCommand (Dhall.MakeExecutable exe) = MakeExecutable (T.unpack exe)
65 | commandDhallToCommand (Dhall.Call p as env proc) = Call (T.unpack p) (T.unpack <$> as) (fmap envVarDhallToEnvVar <$> env) (T.unpack <$> proc)
66 | commandDhallToCommand (Dhall.SymlinkBinary b) = SymlinkBinary (T.unpack b)
67 | commandDhallToCommand (Dhall.SymlinkManpage b s) = SymlinkManpage (T.unpack b) (fromIntegral s)
68 | commandDhallToCommand (Dhall.Write out fp) = Write out (T.unpack fp)
69 | commandDhallToCommand (Dhall.CopyFile src' dest') = CopyFile (T.unpack src') (T.unpack dest')
70 | commandDhallToCommand (Dhall.Symlink t l) = Symlink (T.unpack t) (T.unpack l)
71 | commandDhallToCommand (Dhall.Patch c) = Patch c
72 |
73 | buildVarsToDhallBuildVars :: BuildVars -> Dhall.BuildVars
74 | 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)
75 |
76 | cPkgDhallToCPkg :: Dhall.CPkg -> CPkg
77 | cPkgDhallToCPkg (Dhall.CPkg n v url subdir bldDeps deps cfgCmd buildCmd installCmd) =
78 | CPkg (T.unpack n) (Version v) (T.unpack url) (T.unpack subdir) bldDeps deps configure build install
79 |
80 | where configure cfg = commandDhallToCommand <$> cfgCmd (buildVarsToDhallBuildVars cfg)
81 | build cfg = commandDhallToCommand <$> buildCmd (buildVarsToDhallBuildVars cfg)
82 | install cfg = commandDhallToCommand <$> installCmd (buildVarsToDhallBuildVars cfg)
83 |
--------------------------------------------------------------------------------
/src/Package/C/Triple/Type.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE DeriveAnyClass #-}
2 | {-# LANGUAGE DeriveGeneric #-}
3 | {-# LANGUAGE OverloadedStrings #-}
4 |
5 | module Package.C.Triple.Type ( TargetTriple (..)
6 | , Manufacturer (..)
7 | , Arch (..)
8 | , ABI (..)
9 | , OS (..)
10 | ) where
11 |
12 | import CPkgPrelude
13 | import Data.Text.Prettyprint.Doc.Custom
14 |
15 | -- TODO: are the derived Binary instances inefficient? possibly replace them
16 | -- with handwritten instances...
17 | data TargetTriple = TargetTriple { arch :: Arch
18 | , manufacturer :: Maybe Manufacturer
19 | , os :: OS
20 | , abi :: Maybe ABI
21 | }
22 | deriving (Eq, Ord, Hashable, Binary, Generic, ToDhall)
23 |
24 | instance Pretty TargetTriple where
25 | pretty (TargetTriple a (Just m) o (Just ab)) = dashed [pretty a, pretty m, pretty o, pretty ab]
26 | pretty (TargetTriple a Nothing o (Just ab)) = dashed [pretty a, pretty o, pretty ab]
27 | pretty (TargetTriple a (Just m) o Nothing) = dashed [pretty a, pretty m, pretty o]
28 | pretty (TargetTriple a Nothing o Nothing) = dashed [pretty a, pretty o]
29 |
30 | instance Show TargetTriple where
31 | show = show . pretty
32 |
33 | data Manufacturer = Unknown
34 | | Apple
35 | | IBM
36 | | PC
37 | deriving (Eq, Ord, Hashable, Binary, Generic, ToDhall)
38 |
39 | instance Pretty Manufacturer where
40 | pretty Unknown = "unknown"
41 | pretty Apple = "apple"
42 | pretty IBM = "ibm"
43 | pretty PC = "pc"
44 |
45 | data Arch = X64
46 | | AArch
47 | | Arm
48 | | RISCV64
49 | | PowerPC
50 | | PowerPC64
51 | | PowerPC64le
52 | | Sparc64
53 | | S390x
54 | | Alpha
55 | | M68k
56 | | Mips
57 | | MipsEl
58 | | Mips64
59 | | Mips64El
60 | | X86
61 | | SH4
62 | | HPPA
63 | | HPPA64
64 | | MipsIsa32r6El
65 | | MipsIsa32r6
66 | | MipsIsa64r6El
67 | | MipsIsa64r6
68 | deriving (Eq, Ord, Hashable, Binary, Generic, ToDhall)
69 |
70 | instance Pretty Arch where
71 | pretty X64 = "x86_64"
72 | pretty AArch = "aarch64"
73 | pretty Arm = "arm"
74 | pretty RISCV64 = "riscv64"
75 | pretty PowerPC = "powerpc"
76 | pretty PowerPC64 = "powerpc64"
77 | pretty PowerPC64le = "powerpc64le"
78 | pretty Sparc64 = "sparc64"
79 | pretty S390x = "s390x"
80 | pretty Alpha = "alpha"
81 | pretty M68k = "m68k"
82 | pretty Mips = "mips"
83 | pretty MipsEl = "mipsel"
84 | pretty Mips64 = "mips64"
85 | pretty Mips64El = "mips64el"
86 | pretty X86 = "i686"
87 | pretty SH4 = "sh4"
88 | pretty HPPA = "hppa"
89 | pretty HPPA64 = "hppa64"
90 | pretty MipsIsa32r6El = "mipsisa32r6el"
91 | pretty MipsIsa32r6 = "mipsisa32r6"
92 | pretty MipsIsa64r6El = "mipsisa64r6el"
93 | pretty MipsIsa64r6 = "mipsisa64r6"
94 |
95 | data ABI = GNU
96 | | GNUabi64
97 | | GNUeabi
98 | | GNUeabihf
99 | | GNUspe
100 | | MinGw
101 | deriving (Eq, Ord, Hashable, Binary, Generic, ToDhall)
102 |
103 | instance Pretty ABI where
104 | pretty GNU = "gnu"
105 | pretty GNUabi64 = "gnuabi64"
106 | pretty GNUeabi = "gnueabi"
107 | pretty GNUeabihf = "gnueabihf"
108 | pretty GNUspe = "gnuspe"
109 | pretty MinGw = "mingw32"
110 |
111 | data OS = Darwin
112 | | Dragonfly
113 | | FreeBSD
114 | | Linux
115 | | OpenBSD
116 | | NetBSD
117 | | Solaris
118 | | Windows
119 | | Redox
120 | | Haiku
121 | | IOS
122 | | AIX
123 | | Hurd
124 | | Android
125 | | NoOs
126 | deriving (Eq, Ord, Hashable, Binary, Generic, ToDhall)
127 | -- IRIX? HP UX?
128 |
129 | instance Pretty OS where
130 | pretty Darwin = "darwin"
131 | pretty Dragonfly = "dragonfly"
132 | pretty FreeBSD = "freebsd"
133 | pretty Linux = "linux"
134 | pretty OpenBSD = "openbsd"
135 | pretty NetBSD = "netbsd"
136 | pretty Solaris = "solaris"
137 | pretty Windows = "w64"
138 | pretty Redox = "redox"
139 | pretty Haiku = "haiku"
140 | pretty IOS = "ios"
141 | pretty AIX = "aix"
142 | pretty Hurd = "hurd"
143 | pretty Android = "android"
144 | pretty NoOs = "none"
145 |
--------------------------------------------------------------------------------
/cpkg.cabal:
--------------------------------------------------------------------------------
1 | cabal-version: 1.18
2 | name: cpkg
3 | version: 0.2.5.7
4 | license: BSD3
5 | license-file: LICENSE
6 | copyright: Copyright: (c) 2018-2020 Vanessa McHale
7 | maintainer: vamchale@gmail.com
8 | author: Vanessa McHale
9 | synopsis: Build tool for C
10 | description:
11 | A build tool and package manager configured using [Dhall](https://github.com/dhall-lang/dhall-haskell).
12 |
13 | category: Packaging, Package Management, Dhall, C
14 | build-type: Simple
15 | extra-source-files:
16 | cabal.project
17 | dhall/cpkg-prelude.dhall
18 | dhall/cpkg-types.dhall
19 | pkgs/pkg-set.dhall
20 | pkgs/patches/*.patch
21 |
22 | extra-doc-files:
23 | README.md
24 | CHANGELOG.md
25 |
26 | source-repository head
27 | type: git
28 | location: https://github.com/vmchale/cpkg
29 |
30 | flag development
31 | description: Enable `-Werror`
32 | default: False
33 | manual: True
34 |
35 | library
36 | exposed-modules: Package.C
37 | build-tools: cpphs -any
38 | hs-source-dirs: src
39 | other-modules:
40 | Package.C.Dhall
41 | Package.C.Dhall.Type
42 | Package.C.Type
43 | Package.C.Type.Shared
44 | Package.C.Type.Tree
45 | Package.C.Type.Verbosity
46 | Package.C.Type.Version
47 | Package.C.Type.Vars
48 | Package.C.Triple
49 | Package.C.Triple.Type
50 | Package.C.Triple.Parse
51 | Package.C.Build
52 | Package.C.Build.OS
53 | Package.C.Build.Tree
54 | Package.C.Unpack
55 | Package.C.Error
56 | Package.C.Fetch
57 | Package.C.Monad
58 | Package.C.Db.Type
59 | Package.C.Db.Register
60 | Package.C.Db.Monad
61 | Package.C.Db.Memory
62 | Package.C.Db.GarbageCollect
63 | Package.C.PackageSet
64 | Package.C.Logging
65 | System.Process.Ext
66 | System.Directory.Executable
67 | Data.Text.Prettyprint.Doc.Custom
68 | CPkgPrelude
69 |
70 | default-language: Haskell2010
71 | other-extensions:
72 | DeriveGeneric DeriveAnyClass OverloadedStrings DerivingStrategies
73 | GeneralizedNewtypeDeriving RankNTypes
74 |
75 | ghc-options: -Wall
76 | build-depends:
77 | base >=4.11 && <5,
78 | containers >=0.6.0.0,
79 | text -any,
80 | temporary -any,
81 | bytestring -any,
82 | zlib -any,
83 | bz2 >=0.1.1.0,
84 | lzma -any,
85 | zip-archive -any,
86 | prettyprinter -any,
87 | http-client -any,
88 | http-client-tls -any,
89 | directory >=1.3.1.0,
90 | filepath -any,
91 | process -any,
92 | mtl -any,
93 | hashable -any,
94 | binary -any,
95 | microlens -any,
96 | recursion >=2.2.3.0,
97 | filemanip -any,
98 | network-uri -any,
99 | megaparsec -any,
100 | libarchive >=2.2.5.0,
101 | dir-traverse >=0.2.1.0,
102 | composition-prelude >=1.5.2.0,
103 | lzlib >=0.3.0.0,
104 | dhall >=1.29.0,
105 | zstd -any
106 |
107 | if (flag(development) && impl(ghc <=8.2))
108 | ghc-options: -Werror
109 |
110 | if impl(ghc >=8.0)
111 | ghc-options:
112 | -Wincomplete-uni-patterns -Wincomplete-record-updates
113 | -Wredundant-constraints -Widentities
114 |
115 | if impl(ghc >=8.4)
116 | ghc-options: -Wmissing-export-lists
117 |
118 | executable cpkg
119 | main-is: Main.hs
120 | hs-source-dirs: app
121 | other-modules: Paths_cpkg
122 | default-language: Haskell2010
123 | ghc-options: -threaded -rtsopts "-with-rtsopts=-N -qg" -Wall
124 | build-depends:
125 | base -any,
126 | cpkg -any,
127 | optparse-applicative -any,
128 | directory -any,
129 | text -any,
130 | dhall >=1.29.0
131 |
132 | if (flag(development) && impl(ghc <=8.2))
133 | ghc-options: -Werror
134 |
135 | if impl(ghc >=8.0)
136 | ghc-options:
137 | -Wincomplete-uni-patterns -Wincomplete-record-updates
138 | -Wredundant-constraints -Widentities
139 |
140 | if impl(ghc >=8.4)
141 | ghc-options: -Wmissing-export-lists
142 |
143 | test-suite cpkg-test
144 | type: exitcode-stdio-1.0
145 | main-is: Spec.hs
146 | hs-source-dirs: test
147 | default-language: Haskell2010
148 | ghc-options: -threaded -rtsopts "-with-rtsopts=-N -K1K" -Wall
149 | build-depends:
150 | base -any,
151 | cpkg -any,
152 | hspec -any,
153 | hspec-megaparsec -any,
154 | megaparsec -any
155 |
156 | if flag(development)
157 | ghc-options: -Werror
158 |
159 | if impl(ghc >=8.0)
160 | ghc-options:
161 | -Wincomplete-uni-patterns -Wincomplete-record-updates
162 | -Wredundant-constraints -Widentities
163 |
164 | if impl(ghc >=8.4)
165 | ghc-options: -Wmissing-export-lists
166 |
--------------------------------------------------------------------------------
/pkgs/patches/m4.patch:
--------------------------------------------------------------------------------
1 | diff --color -u lib/fflush.c lib/fflush.c
2 | --- lib/fflush.c 2016-12-31 07:54:41.000000000 -0600
3 | +++ lib/fflush.c 2019-05-24 15:43:00.800903010 -0500
4 | @@ -33,7 +33,7 @@
5 | #undef fflush
6 |
7 |
8 | -#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
9 | +#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
10 |
11 | /* Clear the stream's ungetc buffer, preserving the value of ftello (fp). */
12 | static void
13 | @@ -72,7 +72,7 @@
14 |
15 | #endif
16 |
17 | -#if ! (defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */)
18 | +#if ! (defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */)
19 |
20 | # if (defined __sferror || defined __DragonFly__ || defined __ANDROID__) && defined __SNPT
21 | /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Android */
22 | @@ -148,7 +148,7 @@
23 | if (stream == NULL || ! freading (stream))
24 | return fflush (stream);
25 |
26 | -#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
27 | +#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
28 |
29 | clear_ungetc_buffer_preserving_position (stream);
30 |
31 | diff --color -u lib/fpending.c lib/fpending.c
32 | --- lib/fpending.c 2016-12-31 07:54:41.000000000 -0600
33 | +++ lib/fpending.c 2019-05-24 15:43:00.800903010 -0500
34 | @@ -32,7 +32,7 @@
35 | /* Most systems provide FILE as a struct and the necessary bitmask in
36 | , because they need it for implementing getc() and putc() as
37 | fast macros. */
38 | -#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
39 | +#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
40 | return fp->_IO_write_ptr - fp->_IO_write_base;
41 | #elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
42 | /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Android */
43 | diff --color -u lib/fpurge.c lib/fpurge.c
44 | --- lib/fpurge.c 2016-12-31 07:54:41.000000000 -0600
45 | +++ lib/fpurge.c 2019-05-24 15:43:00.800903010 -0500
46 | @@ -62,7 +62,7 @@
47 | /* Most systems provide FILE as a struct and the necessary bitmask in
48 | , because they need it for implementing getc() and putc() as
49 | fast macros. */
50 | -# if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
51 | +# if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
52 | fp->_IO_read_end = fp->_IO_read_ptr;
53 | fp->_IO_write_ptr = fp->_IO_write_base;
54 | /* Avoid memory leak when there is an active ungetc buffer. */
55 | diff --color -u lib/freadahead.c lib/freadahead.c
56 | --- lib/freadahead.c 2016-12-31 07:54:41.000000000 -0600
57 | +++ lib/freadahead.c 2019-05-24 15:43:00.800903010 -0500
58 | @@ -25,7 +25,7 @@
59 | size_t
60 | freadahead (FILE *fp)
61 | {
62 | -#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
63 | +#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
64 | if (fp->_IO_write_ptr > fp->_IO_write_base)
65 | return 0;
66 | return (fp->_IO_read_end - fp->_IO_read_ptr)
67 | diff --color -u lib/freading.c lib/freading.c
68 | --- lib/freading.c 2016-12-31 07:54:41.000000000 -0600
69 | +++ lib/freading.c 2019-05-24 15:43:00.800903010 -0500
70 | @@ -31,7 +31,7 @@
71 | /* Most systems provide FILE as a struct and the necessary bitmask in
72 | , because they need it for implementing getc() and putc() as
73 | fast macros. */
74 | -# if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
75 | +# if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
76 | return ((fp->_flags & _IO_NO_WRITES) != 0
77 | || ((fp->_flags & (_IO_NO_READS | _IO_CURRENTLY_PUTTING)) == 0
78 | && fp->_IO_read_base != NULL));
79 | diff --color -u lib/fseeko.c lib/fseeko.c
80 | --- lib/fseeko.c 2016-12-31 07:54:41.000000000 -0600
81 | +++ lib/fseeko.c 2019-05-24 15:43:00.800903010 -0500
82 | @@ -47,7 +47,7 @@
83 | #endif
84 |
85 | /* These tests are based on fpurge.c. */
86 | -#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
87 | +#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
88 | if (fp->_IO_read_end == fp->_IO_read_ptr
89 | && fp->_IO_write_ptr == fp->_IO_write_base
90 | && fp->_IO_save_base == NULL)
91 | @@ -123,7 +123,7 @@
92 | return -1;
93 | }
94 |
95 | -#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
96 | +#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
97 | fp->_flags &= ~_IO_EOF_SEEN;
98 | fp->_offset = pos;
99 | #elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
100 | Common subdirectories: lib/glthread and lib/glthread
101 | diff --color -u lib/stdio-impl.h lib/stdio-impl.h
102 | --- lib/stdio-impl.h 2016-12-31 07:54:42.000000000 -0600
103 | +++ lib/stdio-impl.h 2019-05-24 15:43:10.885006876 -0500
104 | @@ -138,3 +138,4 @@
105 | # define _IOERR 0x10
106 |
107 | #endif
108 | +#define _IO_IN_BACKUP 0x100
109 |
--------------------------------------------------------------------------------
/src/Package/C/Build/Tree.hs:
--------------------------------------------------------------------------------
1 | module Package.C.Build.Tree ( buildByName
2 | ) where
3 |
4 | import Control.Recursion
5 | import CPkgPrelude
6 | import Data.Containers.ListUtils (nubOrd)
7 | import Data.List (isInfixOf)
8 | import Package.C.Build
9 | import Package.C.Monad
10 | import Package.C.PackageSet
11 | import Package.C.Type
12 | import Package.C.Type.Tree
13 | import System.Directory (doesDirectoryExist)
14 | import System.FilePath ((>))
15 |
16 | data BuildDirs = BuildDirs { libraries :: [FilePath]
17 | , share :: [FilePath]
18 | , include :: [FilePath]
19 | , binaries :: [FilePath]
20 | }
21 |
22 | getAll :: [BuildDirs] -> BuildDirs
23 | getAll bds =
24 | let go f = concat (f <$> bds)
25 | in BuildDirs (go libraries) (go share) (go include) (go binaries)
26 |
27 | -- in order to prevent the "vanilla" libffi from preceding the *cross* libffi,
28 | -- we filter out any directory that doesn't contain the target triple. this
29 | -- causes further bugs and it's slow
30 | --
31 | -- Really we should allow *all* libdirs for Python/Perl here, since they won't
32 | -- (hopefully) pollute the pkg-config path...
33 | immoralFilter :: Maybe TargetTriple -> [FilePath] -> [FilePath]
34 | immoralFilter Nothing fps = fps
35 | immoralFilter (Just tgt') fps =
36 | let infixDir = show tgt'
37 | in filter (\fp -> infixDir `isInfixOf` fp || "meson" `isInfixOf` fp || "XML-Parser" `isInfixOf` fp || "python3" `isInfixOf` fp) fps -- FIXME: more principled approach
38 |
39 | -- filter out stuff from the path
40 | filterCross :: Maybe TargetTriple -> [FilePath] -> [FilePath]
41 | filterCross Nothing = id
42 | filterCross (Just tgt') =
43 | let infixDir = show tgt'
44 | in filter (\fp -> not (infixDir `isInfixOf` fp) || "ncurses" `isInfixOf` fp)
45 |
46 | buildWithContext :: DepTree CPkg
47 | -> Maybe TargetTriple
48 | -> Bool -- ^ Should we build static libraries?
49 | -> Bool -- ^ Install globally
50 | -> PkgM ()
51 | buildWithContext cTree host sta glob = zygoM' dirAlg buildAlg cTree
52 |
53 | where buildAlg :: DepTreeF CPkg (BuildDirs, ()) -> PkgM ()
54 | buildAlg (DepNodeF c usr preBds) =
55 | buildCPkg c host sta glob usr ds (immoralFilter host ls) is (filterCross host bs)
56 | where (BuildDirs ls ds is bs) = getAll (fst <$> preBds)
57 | buildAlg (BldDepNodeF c preBds) =
58 | buildCPkg c Nothing False False False ds ls is bs -- don't use static libraries for build dependencies
59 | -- also don't install them globally
60 | -- build dependencies are not manual!
61 | where (BuildDirs ls ds is bs) = getAll (fst <$> preBds)
62 |
63 | mkBuildDirs :: MonadIO m => FilePath -> BuildDirs -> m BuildDirs
64 | mkBuildDirs pkgDir (BuildDirs ls ds is bs) = do
65 | let linkDir = pkgDir > "lib"
66 | linkDir64 = pkgDir > "lib64"
67 | includeDir = pkgDir > "include"
68 | dataDir = pkgDir > "share"
69 | binDir = pkgDir > "bin"
70 |
71 | binExists <- liftIO (doesDirectoryExist binDir)
72 | let bins = if binExists
73 | then binDir : bs
74 | else bs
75 |
76 | shareExists <- liftIO (doesDirectoryExist dataDir)
77 | let shares = if shareExists
78 | then dataDir : ds
79 | else ds
80 |
81 | linkExists <- liftIO (doesDirectoryExist linkDir)
82 | link64Exists <- liftIO (doesDirectoryExist linkDir64)
83 |
84 | let linkAppend = if linkExists
85 | then (linkDir :)
86 | else id
87 | let link64Append = if link64Exists
88 | then (linkDir64 :)
89 | else id
90 |
91 | let links = link64Append (linkAppend ls)
92 |
93 | includeExists <- liftIO (doesDirectoryExist includeDir)
94 | let includes = if includeExists
95 | then includeDir : is
96 | else is
97 |
98 | pure (BuildDirs (nubOrd links) (nubOrd shares) (nubOrd includes) (nubOrd bins))
99 |
100 | dirAlg :: DepTreeF CPkg BuildDirs -> PkgM BuildDirs
101 | dirAlg (DepNodeF c _ bds) = do
102 |
103 | let bldDirs@(BuildDirs ls ds is bs) = getAll bds
104 |
105 | buildVars <- getVars host sta ds (immoralFilter host ls) is (filterCross host bs)
106 |
107 | pkgDir <- cPkgToDir c host glob buildVars
108 |
109 | mkBuildDirs pkgDir bldDirs
110 |
111 | dirAlg (BldDepNodeF c bds) = do
112 |
113 | let bldDirs@(BuildDirs ls ds is bs) = getAll bds
114 |
115 | buildVars <- getVars Nothing False ds ls is bs
116 |
117 | pkgDir <- cPkgToDir c Nothing False buildVars
118 |
119 | mkBuildDirs pkgDir bldDirs
120 |
121 | -- TODO: should this parse a string into a TargetTriple instead?
122 | -- | Manually install a package
123 | buildByName :: PackId -> Maybe TargetTriple -> Maybe String -> Bool -> Bool -> PkgM ()
124 | buildByName pkId host pkSet sta glob = do
125 | allPkgs <- liftIO (pkgsM pkId pkSet)
126 | buildWithContext allPkgs host sta glob
127 |
--------------------------------------------------------------------------------
/app/Main.hs:
--------------------------------------------------------------------------------
1 | module Main (main) where
2 |
3 | import Control.Monad (void, when)
4 | import Data.Semigroup
5 | import qualified Data.Text as T
6 | import qualified Data.Version as V
7 | import Dhall.Version (dhallVersionString)
8 | import Options.Applicative hiding (auto)
9 | import Package.C hiding (Command, name)
10 | import qualified Paths_cpkg as P
11 | import System.Directory (doesDirectoryExist, removeDirectoryRecursive)
12 |
13 | cpkgVersion :: V.Version
14 | cpkgVersion = P.version
15 |
16 | data DumpTarget = Linker { _pkgGet :: String }
17 | | Compiler { _pkgGet :: String }
18 | | PkgConfig { _pkgGets :: [String] }
19 | | IncludePath { _pkgGet :: String }
20 | | LibPath { _pkgGet :: String }
21 | | LdLibPath { _pkgGets :: [String] }
22 |
23 | data Command = Install { _pkgName :: String, _verbosity :: Verbosity, _target :: Maybe Platform, _static :: Bool, _global :: Bool, _packageSet :: Maybe String }
24 | | Uninstall { _pkgStr :: String, _verbosity :: Verbosity, _target :: Maybe Platform }
25 | | Check { _dhallFile :: String, _verbosity :: Verbosity }
26 | | CheckSet { _dhallFile :: String, _verbosity :: Verbosity }
27 | | Dump { _dumpTarget :: DumpTarget, _host :: Maybe Platform }
28 | | DumpCabal { _pkgGetsCabal :: [String], _host :: Maybe Platform }
29 | | List { _packageSet :: Maybe String }
30 | | Find { _findPkg :: String }
31 | | Nuke
32 | | NukeCache
33 | | GarbageCollect { _verbosity :: Verbosity }
34 |
35 | verbosityInt :: Parser Int
36 | verbosityInt = length <$>
37 | many (flag' () (short 'v' <> long "verbose" <> help "Turn up verbosity"))
38 |
39 | verbosity :: Parser Verbosity
40 | verbosity = fmap intToVerbosity verbosityInt
41 |
42 | intToVerbosity :: Int -> Verbosity
43 | intToVerbosity 0 = Normal
44 | intToVerbosity 1 = Verbose
45 | intToVerbosity 2 = Loud
46 | intToVerbosity 3 = Diagnostic
47 | intToVerbosity _ = Normal
48 |
49 | wrapper :: ParserInfo Command
50 | wrapper = info (helper <*> versionInfo <*> userCmd)
51 | (fullDesc
52 | <> progDesc "The cpkg build tool and package manager."
53 | <> header "cpkg - a build tool for C")
54 |
55 | versionInfo :: Parser (a -> a)
56 | versionInfo = infoOption vStr (short 'V' <> long "version" <> help "Show version")
57 | where vStr = "cpkg version: " ++ V.showVersion cpkgVersion ++ "\ndhall version: " ++ dhallVersionString ++ "\npackage set: " ++ T.unpack defaultPackageSetHash
58 |
59 | dumpTarget :: Parser DumpTarget
60 | dumpTarget = hsubparser
61 | (command "linker" (info (Linker <$> package) (progDesc "Dump linker flags for a package"))
62 | <> command "compiler" (info (Compiler <$> package) (progDesc "Dump compiler flags for a package"))
63 | <> command "pkg-config" (info (PkgConfig <$> some package) (progDesc "Dump pkg-config path for a package")) -- TODO: make pkg-config recursive or something?
64 | <> command "include" (info (IncludePath <$> package) (progDesc "Dump C_INCLUDE_PATH for a package"))
65 | <> command "library" (info (LibPath <$> package) (progDesc "Dump LD_LIBRARY_PATH or LIBRARY_PATH info for a package"))
66 | <> command "ld-path" (info (LdLibPath <$> some package) (progDesc "Dump LD_LIBRARY_PATH or LIBRARY_PATH for a package"))
67 | )
68 |
69 | userCmd :: Parser Command
70 | userCmd = hsubparser
71 | (command "install" (info install (progDesc "Install a package from the global package set"))
72 | <> command "uninstall" (info uninstall (progDesc "Uninstall a package"))
73 | <> command "check" (info check (progDesc "Check a Dhall expression to ensure it can be used to build a package"))
74 | <> command "check-set" (info checkSet (progDesc "Check a package set defined in Dhall"))
75 | <> command "dump" (info dump (progDesc "Display flags to link against a particular library"))
76 | <> command "dump-cabal" (info dumpCabal (progDesc "Display flags to use with cabal new-build"))
77 | <> command "list" (info list (progDesc "List all available packages"))
78 | <> command "find" (info find (progDesc "Find a package and list information"))
79 | <> command "nuke" (info (pure Nuke) (progDesc "Remove all globally installed libraries"))
80 | <> command "nuke-cache" (info (pure NukeCache) (progDesc "Remove cached soure tarballs"))
81 | <> command "garbage-collect" (info garbageCollect' (progDesc "Garbage collect redundant packages"))
82 | )
83 |
84 | list :: Parser Command
85 | list = List <$> packageSet
86 |
87 | find :: Parser Command
88 | find = Find
89 | <$> argument str
90 | (metavar "PACKAGE"
91 | <> help "Name of package"
92 | )
93 |
94 | ftypeCompletions :: String -> Mod ArgumentFields a
95 | ftypeCompletions ext = completer . bashCompleter $ "file -X '!*." ++ ext ++ "' -o plusdirs"
96 |
97 | dhallCompletions :: Mod ArgumentFields a
98 | dhallCompletions = ftypeCompletions "dhall"
99 |
100 | uninstall :: Parser Command
101 | uninstall = Uninstall
102 | <$> argument str
103 | (metavar "PACKAGE"
104 | <> help "Name of package to uninstall"
105 | <> completer (listIOCompleter allPackages))
106 | <*> verbosity
107 | <*> target
108 |
109 | install :: Parser Command
110 | install = Install
111 | <$> argument str
112 | (metavar "PACKAGE"
113 | <> help "Name of package to install")
114 | <*> verbosity
115 | <*> target
116 | <*> static'
117 | <*> switch
118 | (long "global"
119 | <> short 'g'
120 | <> help "Install globally")
121 | <*> packageSet
122 |
123 | packageSet :: Parser (Maybe String)
124 | packageSet = optional
125 | (strOption
126 | (metavar "EXPRESSION"
127 | <> long "pkg-set"
128 | <> help "Dhall expression for the package set to be used"
129 | ))
130 |
131 | static' :: Parser Bool
132 | static' =
133 | switch
134 | (long "static"
135 | <> help "Build static libaries")
136 |
137 | garbageCollect' :: Parser Command
138 | garbageCollect' = GarbageCollect <$> verbosity
139 |
140 | check :: Parser Command
141 | check = Check <$> dhallFile <*> verbosity
142 |
143 | checkSet :: Parser Command
144 | checkSet = CheckSet <$> dhallFile <*> verbosity
145 |
146 | target :: Parser (Maybe Platform)
147 | target = optional
148 | (strOption
149 | (metavar "TARGET"
150 | <> long "target"
151 | <> help "Host platform, e.g. arm-linux-gnueabihf"
152 | ))
153 |
154 | package :: Parser String
155 | package =
156 | argument str
157 | (metavar "PACKAGE"
158 | <> help "Name of package you want to link against"
159 | <> completer (listIOCompleter allPackages)
160 | )
161 |
162 | dumpCabal :: Parser Command
163 | dumpCabal = DumpCabal
164 | <$> some package
165 | <*> target
166 |
167 | dump :: Parser Command
168 | dump = Dump
169 | <$> dumpTarget
170 | <*> target
171 |
172 | dhallFile :: Parser String
173 | dhallFile =
174 | argument str
175 | (metavar "EXPRESSION"
176 | <> help "File containing a Dhall expression"
177 | <> dhallCompletions
178 | )
179 |
180 | run :: Command -> IO ()
181 | run (Uninstall pkId v host') = do
182 | parsedHost <- parseHostIO host'
183 | runPkgM v $ uninstallPkgByName pkId parsedHost
184 | run (Install pkId v host' sta glob pkSet) = do
185 | parsedHost <- parseHostIO host'
186 | runPkgM v $ buildByName (T.pack pkId) parsedHost pkSet sta glob
187 | run (Check file' v) = void $ getCPkg v file'
188 | run (CheckSet file' v) = void $ getPkgs v file'
189 | run (Dump (Linker name) host) = runPkgM Normal $ printLinkerFlags name host
190 | run (Dump (Compiler name) host) = runPkgM Normal $ printCompilerFlags name host
191 | run (Dump (PkgConfig names) host) = runPkgM Normal $ printPkgConfigPath names host
192 | run (Dump (IncludePath name) host) = runPkgM Normal $ printIncludePath name host
193 | run (Dump (LibPath name) host) = runPkgM Normal $ printLibPath name host
194 | run (Dump (LdLibPath names) host) = runPkgM Normal $ printLdLibPath names host
195 | run (DumpCabal names host) = runPkgM Normal $ printCabalFlags names host
196 | run Nuke = do
197 | pkgDir <- globalPkgDir
198 | exists <- doesDirectoryExist pkgDir
199 | when exists $
200 | removeDirectoryRecursive pkgDir
201 | run NukeCache = cleanCache
202 | run (List pkSet) = displayPackageSet pkSet
203 | run (Find pk) = displayPackage pk
204 | run (GarbageCollect v) = runPkgM v garbageCollect
205 |
206 | main :: IO ()
207 | main = run =<< execParser wrapper
208 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # Upstream
2 | - [ ] Report CBOR decoding?
3 | - [ ] Fix Dhall parser
4 | - [ ] Add typechecking benchmarks
5 | - [ ] Ask how to implement `init`/`tail` in Dhall
6 | - [ ] Also find & replace on strings
7 | - [ ] Maybe fix `acid-state`?
8 | - [ ] Investigate possible upstream bug when downloading `fltk` and unpacking
9 | the `.tar.gz`
10 | - [x] Fix tar library and/or rewrite it
11 | - [x] Dhall space leak
12 | - [ ] Dhall performance problems
13 | - [ ] Fix `hp2pretty` completions to work with `.hp` files alone
14 | - [ ] Investigate performance problems while decoding `index.bin`
15 | - [ ] complain about ncurses 6.1 not cross-compiling
16 | - [ ] complain about Xorg libraries and bad defaults (malloc) related to
17 | cross-compiling
18 | - [ ] definitely complain about intltool
19 | - [ ] complain about m4 (?)
20 | - [ ] Figure out why `libX11` stalls when not watched (i.e. when `-vv` is not
21 | passed...)
22 | - [ ] figure out why `libsepol` doesn't cross-compile
23 | - [ ] `xextproto` doesn't like `aarch64`
24 | - [ ] ImageMagick fails on ARM
25 | - [ ] `wget` doesn't work with latest gnutls
26 | - [ ] Report bug to LFS: libevent depends on openssl as they have configured it...
27 | - [ ] OpenSSH fails to cross-compile
28 | - [ ] bz2 fails to unpack glu?
29 | # Libraries
30 | - [ ] Consider splitting off library for parsing triples &c.
31 | # Code Maintenance
32 | - [ ] Use a more sensible monad
33 | - [ ] Stop being a mess
34 | # Documentation
35 | - [ ] Document use of `cabal.project` files (which is simpler...)
36 | # Features
37 | - [ ] Source depends like `CImg`
38 | - [ ] Something like cabal flags - enable exif with feh, for example...
39 | - [ ] Pass verbosity to configuration/build script
40 | - [ ] Constraint solver
41 | - [ ] Build/handle preprocessors
42 | - [ ] Don't try to use cross-compiler on preprocessors
43 | - [x] Nix-style builds
44 | - [x] Garbage collection
45 | - [ ] Make it less crappy
46 | - [ ] Caching
47 | - [ ] Cache global package set?
48 | - [ ] `unpack` subcommand for packages
49 | - [ ] Cabal integration? Make it usable as a package for `Setup.hs` files :o
50 | - [ ] Better Haddock API; expose more types
51 | - [ ] Allow a package's function to specify a `pkg-config` dir, etc.
52 | - [ ] Bootstrap "fancy" tar?
53 | - [ ] Package "components"? Like cabal: build executables or not...
54 | - [ ] Symlink manpages
55 | - [ ] Completions
56 | - [ ] `cpkg install` should use `cpkg list`?
57 | - [ ] Custom package sets
58 | - [ ] Haskell library API should be better
59 | - [ ] `cpkg list` should show what binaries it provides
60 | - [ ] `test` should map to commands such as `make check`; should not be run when
61 | cross-compiling
62 | - [ ] `pkgRuntimeDeps` field?
63 | - [ ] append to `cabal.project` file
64 | - [ ] pass `pi@32.32.43.00` or whatever on the command-line?
65 | - [ ] Add IA64 (itanium) support
66 | - [ ] Add HPUX/HPUX64 support
67 | - [ ] Store build logs - options/environment variables, etc.
68 | # Performance
69 | - [ ] Dhall is slow
70 | # Bugs
71 | - [ ] Shouldn't be able to `cpkg dump compiler sed` since it provides no
72 | libraries
73 | - [ ] Figure out `ACLOCAL_PATH`
74 | - [ ] Fails when symlink already exists
75 | - [ ] Cross-compile shouldn't symlink
76 | - [ ] If X depends on Y, Z and Y depends on Z, then it will not link things
77 | correctly...
78 | - [ ] Figure out `PERL5LIB` variable
79 | # Deficiencies
80 | - [ ] Get rid of `symlinkLibrary`? And just use `symlink`...
81 | - [ ] Cache package downloads globally
82 | - [ ] No database w/ graph right now
83 | - [ ] Build step should take OS as an argument
84 | - [ ] Make e.g. `vim` depend on `glibc`
85 | - [ ] Get rid of annoying `LD_PRELOAD` hack?
86 | - [ ] dhall library should prefer `symlink` to `copyFile` when possible? hmm
87 | # Testing
88 | - [ ] Maintainer subcommand to build every single package
89 | # Packages
90 | - [ ] bash
91 | - [ ] librsvg
92 | - [ ] https://github.com/linux-noah/noah
93 | - [ ] GHC cross-compiler?
94 | - [ ] https://sourceforge.net/projects/infozip/files/
95 | - [ ] fdupes
96 | - [ ] Figlet
97 | - [ ] http://www.linuxfromscratch.org/blfs/view/7.5/postlfs/acl.html
98 | - [ ] GHC (`https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-src.tar.xz`)
99 | & cross-compiler
100 | - [ ] weighttp
101 | - [ ] `patscc`
102 | - [ ] http://www.qhull.org/download/qhull-2019-src-7.3.2.tgz
103 | - [ ] `rustc`
104 | - [ ] https://github.com/ZBar/ZBar
105 | - [ ] Doxygen
106 | - [ ] libXcursor
107 | - [ ] exif, libexif-gtk, gexif (https://libexif.github.io/)
108 | - [ ] nomacs
109 | - [ ] FFmpeg
110 | - [ ] https://ftp.gnu.org/gnu/texinfo/ ?
111 | - [ ] charset (?)
112 | - [ ] weighttpd https://github.com/lighttpd/weighttp
113 | - [ ] https://sourceware.org/newlib/
114 | - [ ] https://labs.tomasino.org/gnu-recutils/
115 | - [ ] fish
116 | - [ ] libtizcore
117 | - [ ] ghostscript http://www.linuxfromscratch.org/blfs/view/svn/pst/gs.html
118 | - [ ] https://github.com/yaml/libyaml
119 | - [ ] https://mosh.org/mosh-1.3.2.tar.gz
120 | - [ ] http://www.linuxfromscratch.org/blfs/view/svn/general/boost.html
121 | - [ ] brlcad https://jaist.dl.sourceforge.net/project/brlcad/BRL-CAD%20Source/7.28.0/brlcad-7.28.0.tar.bz2
122 | - [ ] gstreamer-video
123 | - [ ] ragel
124 | - [ ] https://ftp.gnu.org/gnu/parallel/parallel-20181222.tar.bz2
125 | - [ ] http://savannah.gnu.org/projects/patch/
126 | - [ ] Blender https://download.blender.org/source/blender-2.79b.tar.gz
127 | - [ ] http://www.ibiblio.org/pub/Linux/utils/file/symlinks-1.4.tar.gz
128 | - [ ] http://www.linuxfromscratch.org/blfs/view/8.2/general/tree.html
129 | - [ ] libsigsegv
130 | - [ ] pyqt5
131 | - [ ] weirdo levenshtein distance in ATS
132 | - [ ] https://github.com/jmcnamara/libxlsxwriter/archive/RELEASE_0.8.4.tar.gz
133 | - [ ] http://www.linuxfromscratch.org/blfs/view/8.3/postlfs/cracklib.html
134 | - [ ] https://github.com/gildor2/fast_zlib
135 | - [ ] grep
136 | - [ ] https://github.com/chapel-lang/chapel/releases/download/1.18.0/chapel-1.18.0.tar.gz (https://chapel-lang.org/docs/usingchapel/QUICKSTART.html)
137 | - [ ] ed
138 | - [ ] cloc
139 | - [ ] libpeas
140 | - [ ] libcaca
141 | - [ ] alarm, pread, top, htop, kill, grep
142 | - [ ] http://www.linuxfromscratch.org/blfs/view/8.1/pst/xmlto.html
143 | - [ ] https://liquidtelecom.dl.sourceforge.net/project/schilytools/schily-2018-12-21.tar.bz2
144 | - [ ] https://ftp.gnu.org/gnu/autogen/rel5.18.16/
145 | - [ ] https://github.com/pkgconf/pkgconf
146 | - [ ] http://www.linuxfromscratch.org/lfs/view/6.6/appendices/dependencies.html
147 | - [ ] https://github.com/scipy/scipy/releases/download/v1.2.0/scipy-1.2.0.tar.xz
148 | - [ ] Perl wrapper like `mkPy3Wrapper`
149 | - [ ] http://www.linuxfromscratch.org/blfs/view/cvs/basicnet/glib-networking.html
150 | - [ ] http://www.linuxfromscratch.org/blfs/view/cvs/gnome/gexiv2.html
151 | - [ ] http://www.linuxfromscratch.org/blfs/view/8.3/x/x7driver.html#libinput
152 | - [ ] http://luajit.org/index.html
153 | - [ ] https://github.com/mquinson/po4a
154 | - [ ] texinfo/help2man
155 | - [ ] libutemper
156 | - [ ] https://www.gimp.org/source/#gimp-requirements
157 | - [ ] https://github.com/GNOME/cheese
158 | - [ ] http://trousers.sourceforge.net/
159 | - [ ] https://www.gnu.org/software/libidn/#libidn2
160 | - [ ] https://nlnetlabs.nl/projects/unbound/about/
161 | - [ ] https://www.gnupg.org/ftp/gcrypt/pinentry/pinentry-1.1.0.tar.bz2
162 | - [ ] http://aa-project.sourceforge.net/aalib/
163 | - [ ] https://www.gnupg.org/ftp/gcrypt/ntbtls/ntbtls-0.1.2.tar.bz2
164 | - [ ] https://github.com/GNOME/libgudev
165 | - [ ] nss?
166 | - [ ] libXcursor
167 | - [ ] scrot (https://github.com/dreamer/scrot/releases)
168 | - [ ] http://download.redis.io/releases/redis-5.0.3.tar.gz
169 | - [ ] Rarian
170 | - [ ] https://github.com/garabik/unicode/releases
171 | - [ ] evince
172 | - [ ] https://github.com/GNOME/libgweather
173 | - [ ] GIMP
174 | - [ ] libav cross-compile
175 | - [ ] https://github.com/mtoyoda/sl/releases
176 | - [ ] libsocketcap
177 | - [ ] https://github.com/pinard/paxutils/releases
178 | - [ ] https://github.com/aperezdc/signify
179 | - [ ] zstd
180 | - [ ] lz4
181 | - [ ] oclint
182 | - [ ] https://www.cs.ubc.ca/research/flann/
183 | - [ ] pdftotext http://www.xpdfreader.com/download.html
184 | - [ ] Firefox
185 | - [ ] github-linguist (??)
186 | - [ ] https://github.com/microsoft/mimalloc
187 | - [ ] http://www.linuxfromscratch.org/blfs/view/8.3/kde/okular5.html
188 | - [ ] http://cimg.eu/links.shtml
189 | - [ ] http://www.linuxfromscratch.org/blfs/view/svn/gnome/nautilus.html
190 | - [ ] wxWidgets/erlang
191 | - [ ] http://download.savannah.gnu.org/releases/lzip/tarlz/
192 | - [ ] https://github.com/NLnetLabs/unbound
193 | - [ ] https://github.com/google/brotli/releases
194 | - [ ] https://www.gnu.org/software/gsl/
195 | # Documentation
196 | - [ ] Write a manpage
197 | - [ ] Documentation in
198 | - [ ] French
199 | - [ ] German
200 | - [ ] Write `info` thing like `info sed`
201 | # Dhall Libraries
202 | - [ ] `mkExe` and `makeExe` are too similar
203 | # Tests
204 |
--------------------------------------------------------------------------------
/src/Package/C/Build.hs:
--------------------------------------------------------------------------------
1 | module Package.C.Build ( buildCPkg
2 | , getVars
3 | , cPkgToDir
4 | ) where
5 |
6 | import Control.Concurrent (getNumCapabilities)
7 | import CPkgPrelude
8 | import Data.List (isInfixOf)
9 | import Data.Maybe (isJust)
10 | import qualified Data.Text as T
11 | import qualified Data.Text.IO as TIO
12 | import Package.C.Build.OS
13 | import Package.C.Db.Register
14 | import Package.C.Fetch
15 | import Package.C.Logging
16 | import Package.C.Monad
17 | import Package.C.Type
18 | import System.Directory
19 | import System.Directory.Executable (mkExecutable)
20 | import System.Directory.Recursive (getSubdirsRecursive)
21 | import System.FilePath (takeDirectory, takeFileName, (>))
22 | import System.FilePath.Glob
23 | import System.IO.Temp (withSystemTempDirectory)
24 | import System.Process
25 | import System.Process.Ext
26 |
27 | envVarSplit :: EnvVar -> (String, String)
28 | envVarSplit (EnvVar ev x) = (ev, x)
29 |
30 | replaceSymlink :: FilePath -> FilePath -> IO ()
31 | replaceSymlink actual link = do
32 | bf <- doesFileExist link
33 | if bf
34 | then removeFile link
35 | else do
36 | bd <- doesDirectoryExist link
37 | when bd $ removeDirectoryLink link
38 | createFileLink actual link
39 |
40 | stepToProc :: FilePath -- ^ Package build directory
41 | -> FilePath -- ^ Package install directory
42 | -> Command
43 | -> PkgM ()
44 | stepToProc fp _ (Call p as envs dir') = do
45 | let dir'' = maybe fp (fp >) dir'
46 | envVars = fmap envVarSplit <$> envs
47 | putDiagnostic ("Running " ++ p ++ " with arguments " ++ unwords as ++ " in directory " ++ dir'' ++ " with environment " ++ show envVars)
48 | waitProcess $ (proc p as) { cwd = Just dir'', std_in = CreatePipe, env = envVars }
49 | stepToProc dir' _ (MakeExecutable fp) = do
50 | putDiagnostic ("Marking " ++ (dir' > fp) ++ " as executable...")
51 | liftIO $ mkExecutable (dir' > fp)
52 | stepToProc dir' _ (CreateDirectory d) = do
53 | putDiagnostic ("Creating directory " ++ (dir' > d) ++ "...")
54 | liftIO $ createDirectoryIfMissing True (dir' > d)
55 | stepToProc _ p (SymlinkBinary file') = do
56 | binDir <- (> "bin") <$> globalPkgDir
57 | let actualBin = p > file'
58 | liftIO $ createDirectoryIfMissing True binDir
59 | liftIO $ replaceSymlink actualBin (binDir > takeFileName file')
60 | stepToProc _ p (SymlinkManpage file' sec) = do
61 | manDir <- (> ("share" > "man" > "man" ++ show sec)) <$> globalPkgDir
62 | let actualMan = p > file'
63 | liftIO $ createDirectoryIfMissing True manDir
64 | liftIO $ replaceSymlink actualMan (manDir > takeFileName file')
65 | stepToProc _ p (Symlink tgt' lnk) = do
66 | let linkAbs = p > lnk
67 | putDiagnostic ("Creating directory" ++ takeDirectory linkAbs ++ "...")
68 | liftIO $ createDirectoryIfMissing True (takeDirectory linkAbs)
69 | -- TODO: diagnostics for symlinks
70 | liftIO $ replaceSymlink (p > tgt') linkAbs
71 | stepToProc dir' _ (Write out fp) = do
72 | let fpAbs = dir' > fp
73 | putDiagnostic ("Writing\n" ++ T.unpack out ++ "\n in file" ++ fpAbs)
74 | liftIO (TIO.writeFile fpAbs out)
75 | stepToProc dir' p (CopyFile src' dest') = do
76 | let absSrc = dir' > src'
77 | absDest = p > dest'
78 | putDiagnostic ("Copying file " ++ absSrc ++ " to " ++ absDest ++ "...")
79 | liftIO $ createDirectoryIfMissing True (takeDirectory absDest)
80 | liftIO $ copyFileWithMetadata absSrc absDest
81 | stepToProc dir' _ (Patch contents') = do
82 | liftIO $ TIO.writeFile (dir' > "step.patch") contents'
83 | waitProcess $ (proc "patch" ["-p0", "-i", "step.patch"]) { cwd = Just dir' }
84 |
85 | processSteps :: (Traversable t)
86 | => FilePath -- ^ Build directory
87 | -> FilePath -- ^ Install directory
88 | -> t Command
89 | -> PkgM ()
90 | processSteps pkgDir instDir = traverse_ (stepToProc pkgDir instDir)
91 |
92 | configureInDir :: CPkg
93 | -> BuildVars
94 | -> FilePath -- ^ Build directory
95 | -> PkgM ()
96 | configureInDir cpkg cfg p =
97 |
98 | let steps = configureCommand cpkg cfg
99 | in
100 | putNormal ("Configuring " ++ pkgName cpkg) *>
101 | processSteps p (installDir cfg) steps
102 |
103 | buildInDir :: CPkg
104 | -> BuildVars
105 | -> FilePath -- ^ Build directory
106 | -> FilePath -- ^ Install directory
107 | -> PkgM ()
108 | buildInDir cpkg cfg p p' = do
109 | putNormal ("Building " ++ pkgName cpkg)
110 | processSteps p p' (buildCommand cpkg cfg)
111 |
112 | installInDir :: CPkg
113 | -> BuildVars
114 | -> FilePath -- ^ Build directory
115 | -> FilePath -- ^ Install directory
116 | -> PkgM ()
117 | installInDir cpkg cfg p p' =
118 | putNormal ("Installing " ++ pkgName cpkg) *>
119 | processSteps p p' (installCommand cpkg cfg)
120 |
121 | fetchCPkg :: CPkg
122 | -> FilePath -- ^ Directory for intermediate build files
123 | -> PkgM ()
124 | fetchCPkg cpkg = fetchUrl (pkgUrl cpkg) (pkgName cpkg)
125 |
126 | buildCPkg :: CPkg
127 | -> Maybe TargetTriple
128 | -> Bool -- ^ Should we build static libraries?
129 | -> Bool -- ^ Should we install globally?
130 | -> Bool -- ^ Was this package installed manually?
131 | -> [FilePath] -- ^ Shared data directories
132 | -> [FilePath] -- ^ Library directories
133 | -> [FilePath] -- ^ Include directories
134 | -> [FilePath] -- ^ Directories to add to @PATH@
135 | -> PkgM ()
136 | buildCPkg cpkg host sta glob usr shr libs incls bins = do
137 |
138 | buildVars <- getVars host sta shr libs incls bins
139 |
140 | -- TODO: use a real database
141 | installed <- packageInstalled cpkg host glob buildVars
142 |
143 | when installed $
144 | putDiagnostic ("Package " ++ pkgName cpkg ++ " already installed, skipping.")
145 |
146 | unless installed $
147 | forceBuildCPkg cpkg host glob usr buildVars
148 |
149 | getPreloads :: [ FilePath ] -> IO [ FilePath ]
150 | getPreloads =
151 | fmap concat . traverse (\fp -> namesMatching (fp > "*.so"))
152 |
153 | -- only really suitable for hashing at this point, since we use @""@ as the
154 | -- install directory. we use this to get a hash which we then use to get the
155 | -- *real* install directory, which we then use with @configureVars@ to set
156 | -- things up correctly - otherwise we would have a circularity
157 | getVars :: Maybe TargetTriple
158 | -> Bool -- ^ Should we build static libraries?
159 | -> [FilePath] -- ^ Shared data directories
160 | -> [FilePath] -- ^ Library directories
161 | -> [FilePath] -- ^ Include directories
162 | -> [FilePath] -- ^ Directories to add to @PATH@
163 | -> PkgM BuildVars
164 | getVars host sta shr links incls bins = do
165 | nproc <- liftIO getNumCapabilities
166 | pure (BuildVars "" "" host (isJust host) incls [] shr links bins dhallOS dhallArch sta nproc)
167 | -- we don't run getPreloads until later because that might be slow
168 |
169 | -- diagnosticDirectory :: String -> (FilePath -> m a) -> m a
170 | -- diagnosticDirectory s f = f (s ++ "-diagnostic")
171 |
172 | getSubdirsWrap :: FilePath -> IO [FilePath]
173 | getSubdirsWrap fp = do
174 | b <- doesDirectoryExist fp
175 | if b
176 | then (fp:) <$> getSubdirsRecursive fp
177 | else pure []
178 |
179 | -- TODO: more complicated solver, garbage collector, and all that.
180 | -- Basically nix-style builds for C libraries
181 | forceBuildCPkg :: CPkg
182 | -> Maybe TargetTriple
183 | -> Bool
184 | -> Bool -- ^ Manually installed?
185 | -> BuildVars
186 | -> PkgM ()
187 | forceBuildCPkg cpkg host glob usr buildVars = do
188 |
189 | pkgDir <- cPkgToDir cpkg host glob buildVars
190 |
191 | liftIO $ createDirectoryIfMissing True pkgDir
192 |
193 | withSystemTempDirectory "cpkg" $ \p -> do
194 | -- diagnosticDirectory "cpkg" $ \p -> do
195 |
196 | putDiagnostic ("Setting up temporary directory in " ++ p)
197 |
198 | fetchCPkg cpkg p
199 |
200 | pAbs <- liftIO (makeAbsolute p)
201 |
202 | let p' = pAbs > pkgSubdir cpkg
203 |
204 | lds <- liftIO $ do
205 | linkSubdirs <- concat <$> traverse getSubdirsWrap (linkDirs buildVars)
206 | -- FIXME: this seems stupid
207 | let curses = not . ("curses" `isInfixOf`)
208 | getPreloads $ filter curses linkSubdirs
209 |
210 | let buildConfigured = buildVars { installDir = pkgDir, currentDir = pAbs, preloadLibs = lds }
211 |
212 | configureInDir cpkg buildConfigured p'
213 |
214 | buildInDir cpkg buildConfigured p' pkgDir
215 |
216 | installInDir cpkg buildConfigured p' pkgDir
217 |
218 | registerPkg cpkg host glob usr buildVars -- not configured
219 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cpkg
2 |
3 | [](https://matrix.hackage.haskell.org/package/cpkg)
4 | [](http://hackage.haskell.org/package/cpkg)
5 | [](https://hackage.haskell.org/package/cpkg)
6 |
7 | `cpkg` is a build tool for C with a particular emphasis on cross compilation.
8 | It is configured using
9 | [Dhall](http://github.com/dhall-lang/dhall-haskell).
10 |
11 | By considering a package to be a *function* taking a `cpkg`-supplied
12 | installation directory to a series of steps, we can effectively package
13 | C projects with diverse build systems and handle dependencies between them.
14 |
15 | This tool provides reasonably good support for cross-compilation of C projects
16 | and packages. It is not a full-fledged package manager.
17 |
18 | - [Installation](#installation)
19 | - [Shell Completions](#shell-completions)
20 | - [Packages](#packages)
21 | - [Example](#example)
22 | - [Configuration](#configuration)
23 | - [Dhall Prelude](#dhall-prelude)
24 | - [Cabal Integration](#cabal-integration)
25 | - [Known Deficiencies](#known-deficiences)
26 | - [Security](#security)
27 | - [Performance](#performance)
28 | - [Dependency Solver](#dependency-solver)
29 | - [Garbage Collection](#garbage-collection)
30 | - [Contents](#contents)
31 |
32 | ## Installation
33 |
34 | ```
35 | cabal new-install cpkg
36 | ```
37 |
38 | ### Shell Completions
39 |
40 | Add the following to your `~/.bashrc` for shell completions:
41 |
42 | ```
43 | eval "$(cpkg --bash-completion-script cpkg)"
44 | ```
45 |
46 | ### Packages
47 |
48 | To view available packages, use `cpkg list`
49 |
50 | ```
51 | vanessa@thinkpad ~/programming/haskell/done/cpkg 🌸 cpkg list
52 |
53 | autoconf
54 | url: https://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.xz
55 | version: 2.69
56 | build dependencies: m4
57 |
58 |
59 | automake
60 | url: https://ftp.gnu.org/gnu/automake/automake-1.16.1.tar.xz
61 | version: 1.16.1
62 | build dependencies: autoconf
63 |
64 |
65 | at-spi2-atk
66 | url: http://ftp.gnome.org/pub/gnome/sources/at-spi2-atk/2.30/at-spi2-atk-2.30.0.tar.xz
67 | version: 2.30.0
68 | dependencies: at-spi2-core, atk, libxml2
69 | build dependencies: meson, ninja
70 |
71 |
72 | at-spi2-core
73 | url: http://ftp.gnome.org/pub/gnome/sources/at-spi2-core/2.30/at-spi2-core-2.30.0.tar.xz
74 | version: 2.30.0
75 | dependencies: libXtst, glib
76 | build dependencies: meson, ninja
77 |
78 |
79 | atk
80 | url: https://ftp.gnome.org/pub/gnome/sources/atk/2.30/atk-2.30.0.tar.xz
81 | version: 2.30.0
82 | build dependencies: gobject-introspection
83 | ⋮
84 | ```
85 |
86 |
87 | ## Example
88 |
89 | To install `tar`:
90 |
91 | ```
92 | cpkg install tar
93 | ```
94 |
95 | To install `emacs`:
96 |
97 | ```
98 | cpkg install emacs
99 | ```
100 |
101 | ### Configuration
102 |
103 | Here is the configuration for Lua:
104 |
105 | ```dhall
106 | let prelude = https://raw.githubusercontent.com/vmchale/cpkg/master/dhall/cpkg-prelude.dhall
107 | in
108 |
109 | let lua =
110 | λ(v : List Natural) →
111 | let printLuaOS =
112 | λ(os : types.OS) →
113 | merge
114 | { FreeBSD = λ(_ : {}) → "freebsd"
115 | , OpenBSD = λ(_ : {}) → "bsd"
116 | , NetBSD = λ(_ : {}) → "bsd"
117 | , Solaris = λ(_ : {}) → "solaris"
118 | , Dragonfly = λ(_ : {}) → "bsd"
119 | , Linux = λ(_ : {}) → "linux"
120 | , Darwin = λ(_ : {}) → "macosx"
121 | , Windows = λ(_ : {}) → "mingw"
122 | , Redox = λ(_ : {}) → "generic"
123 | , Haiku = λ(_ : {}) → "generic"
124 | , IOS = λ(_ : {}) → "generic"
125 | , AIX = λ(_ : {}) → "generic"
126 | , Hurd = λ(_ : {}) → "generic"
127 | , Android = λ(_ : {}) → "generic"
128 | , NoOs = λ(_ : {}) → "c89"
129 | }
130 | os
131 | in
132 |
133 | let luaBuild =
134 | λ(cfg : types.BuildVars) →
135 | let cc = prelude.mkCCArg cfg
136 | in
137 |
138 | let ldflags =
139 | (prelude.mkLDFlags cfg.linkDirs).value
140 | in
141 |
142 | let cflags =
143 | (prelude.mkCFlags cfg.includeDirs).value
144 | in
145 |
146 | let os =
147 | prelude.osCfg cfg
148 | in
149 |
150 | [ prelude.call (prelude.defaultCall ⫽ { program = "make"
151 | , arguments = cc # [ printLuaOS os, "MYLDFLAGS=${ldflags}", "MYCFLAGS=${cflags}", "MYLIBS=-lncurses" ]
152 | })
153 | ]
154 | in
155 |
156 | let luaInstall =
157 | λ(cfg : types.BuildVars) →
158 | [ prelude.call (prelude.defaultCall ⫽ { program = "make"
159 | , arguments = [ "install", "INSTALL_TOP=${cfg.installDir}" ]
160 | }) ]
161 | # prelude.symlinkBinaries [ "bin/lua", "bin/luac" ]
162 | in
163 |
164 | prelude.simplePackage { name = "lua", version = v } ⫽
165 | { pkgUrl = "http://www.lua.org/ftp/lua-${prelude.showVersion v}.tar.gz"
166 | , configureCommand = prelude.doNothing
167 | , buildCommand = luaBuild
168 | , installCommand = luaInstall
169 | , pkgDeps = [ prelude.unbounded "readline"
170 | , prelude.unbounded "ncurses"
171 | ]
172 | }
173 | in
174 |
175 | lua [5,3,5]
176 | ```
177 |
178 | ### Cabal Integration
179 |
180 | After running
181 |
182 | ```
183 | cpkg install libX11 --target=arm-linux-gnueabihf
184 | cpkg install libXext --target=arm-linux-gnueabihf
185 | cpkg install libXrandr --target=arm-linux-gnueabihf
186 | cpkg install libXinerama --target=arm-linux-gnueabihf
187 | cpkg install libXScrnSaver --target=arm-linux-gnueabihf
188 | ```
189 |
190 | You can dump flags to be passed to cabal with
191 |
192 | ```
193 | cpkg dump-cabal libX11 libXext libXrandr libXinerama libXScrnSaver --target=arm-linux-gnueabihf
194 | ```
195 |
196 | which will produce something like
197 |
198 | ```
199 | --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
200 | ```
201 |
202 | This could be used, for example, to cross-compile `xmonad`, viz.
203 |
204 | ```
205 | 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)
206 | ```
207 |
208 | ### Dhall Prelude
209 |
210 | There is
211 | a [prelude](https://github.com/vmchale/cpkg/blob/master/dhall/cpkg-prelude.dhall)
212 | available containing functions which simplify the process of writing package
213 | descriptions. As an example, we can install `sed`
214 |
215 | ```dhall
216 | let prelude = https://raw.githubusercontent.com/vmchale/cpkg/master/dhall/cpkg-prelude.dhall
217 | in
218 |
219 | let sed =
220 | λ(v : List Natural) →
221 | prelude.makeGnuExe { name = "sed", version = v }
222 | in
223 |
224 | sed [4,5]
225 | ```
226 |
227 | ## Known Deficiencies
228 |
229 | ### Security
230 |
231 | This tool is insecure.
232 |
233 | ### Performance
234 |
235 | This tool is not performant.
236 |
237 | ### Dependency Solver
238 |
239 | Currently, there is no dependency solver. It should be relatively easy to add
240 | a version-based dependency solver to the code.
241 |
242 | ### Garbage Collection
243 |
244 | Currently, there is no garbage collector à la `$ nix-collect-garbage`. This will
245 | *not* be relatively easy to add, because it will require that the global package
246 | index be re-implemented (ideally using a proper database).
247 |
248 | ## Contents
249 |
250 | Lovingly provided by [polyglot](https://github.com/vmchale/polyglot):
251 |
252 | ```
253 | ───────────────────────────────────────────────────────────────────────────────
254 | Language Files Lines Code Comments Blanks
255 | ───────────────────────────────────────────────────────────────────────────────
256 | Bash 4 58 49 3 6
257 | Cabal 1 165 147 0 18
258 | Cabal Project 1 4 3 0 1
259 | Dhall 5 6412 5724 0 688
260 | Haskell 32 1999 1643 37 319
261 | Makefile 1 12 8 0 4
262 | Markdown 3 556 448 0 108
263 | YAML 4 114 110 0 4
264 | ───────────────────────────────────────────────────────────────────────────────
265 | Total 51 9320 8132 40 1148
266 | ───────────────────────────────────────────────────────────────────────────────
267 | ```
268 |
--------------------------------------------------------------------------------
/src/Package/C/Db/Register.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE FlexibleContexts #-}
2 | {-# LANGUAGE RankNTypes #-}
3 |
4 | -- TODO: a lot of the stuff in this module could be made pure so that it only
5 | -- gets called once
6 | module Package.C.Db.Register ( registerPkg
7 | , unregisterPkg
8 | , uninstallPkg
9 | , uninstallPkgByName
10 | , installedDb
11 | , lookupOrFail
12 | , cPkgToDir
13 | , globalPkgDir
14 | , printCompilerFlags
15 | , printLinkerFlags
16 | , printPkgConfigPath
17 | , printIncludePath
18 | , printLibPath
19 | , printCabalFlags
20 | , printLdLibPath
21 | , packageInstalled
22 | , allPackages
23 | , parseHostIO
24 | , Platform
25 | ) where
26 |
27 | import Control.Monad.Reader
28 | import Control.Monad.State (modify)
29 | import CPkgPrelude
30 | import Data.Binary (encode)
31 | import qualified Data.ByteString.Lazy as BSL
32 | import Data.Hashable (Hashable (..))
33 | import Data.List (intercalate)
34 | import qualified Data.Set as S
35 | import Numeric (showHex)
36 | import Package.C.Db.Memory
37 | import Package.C.Db.Monad
38 | import Package.C.Db.Type
39 | import Package.C.Error
40 | import Package.C.Logging
41 | import Package.C.Triple
42 | import Package.C.Type hiding (Dep (name))
43 |
44 | type Platform = String
45 | type FlagPrint = forall m. MonadIO m => BuildCfg -> m String
46 |
47 | allPackages :: IO [String]
48 | allPackages = do
49 | (InstallDb index) <- strictIndex
50 | pure (buildName <$> toList index)
51 |
52 | printCompilerFlags :: (MonadIO m, MonadDb m) => String -> Maybe Platform -> m ()
53 | printCompilerFlags = printFlagsWith buildCfgToCFlags
54 |
55 | printLinkerFlags :: (MonadIO m, MonadDb m) => String -> Maybe Platform -> m ()
56 | printLinkerFlags = printFlagsWith buildCfgToLinkerFlags
57 |
58 | printPkgConfigPath :: (MonadIO m, MonadDb m) => [String] -> Maybe Platform -> m ()
59 | printPkgConfigPath = printMany (liftIO . putStrLn <=< (fmap (intercalate ":") . traverse buildCfgToPkgConfigPath))
60 |
61 | printIncludePath :: (MonadIO m, MonadDb m) => String -> Maybe Platform -> m ()
62 | printIncludePath = printFlagsWith buildCfgToIncludePath
63 |
64 | printLibPath :: (MonadIO m, MonadDb m) => String -> Maybe Platform -> m ()
65 | printLibPath = printFlagsWith buildCfgToLibPath
66 |
67 | parseHostIO :: MonadIO m => Maybe Platform -> m (Maybe TargetTriple)
68 | parseHostIO (Just x) = fmap Just (parseTripleIO x)
69 | parseHostIO Nothing = pure Nothing
70 |
71 | printFlagsWith :: (MonadIO m, MonadDb m) => FlagPrint -> String -> Maybe Platform -> m ()
72 | printFlagsWith f name host = do
73 |
74 | parsedHost <- parseHostIO host
75 |
76 | maybePackage <- lookupPackage name parsedHost
77 |
78 | case maybePackage of
79 | Nothing -> indexError name
80 | Just p -> liftIO (putStrLn =<< f p)
81 |
82 | printMany :: (MonadIO m, MonadDb m) => ([BuildCfg] -> m ()) -> [String] -> Maybe Platform -> m ()
83 | printMany f names host = do
84 |
85 | parsedHost <- parseHostIO host
86 |
87 | maybePackages <- sequenceA <$> traverse (\n -> lookupPackage n parsedHost) names
88 |
89 | case maybePackages of
90 | Nothing -> indexError (head names)
91 | Just ps -> f ps
92 |
93 | printLdLibPath :: (MonadIO m, MonadDb m) => [String] -> Maybe Platform -> m ()
94 | printLdLibPath = printMany (liftIO . putStrLn <=< (fmap (intercalate ":") . traverse buildCfgToLibPath))
95 |
96 | printCabalFlags :: (MonadIO m, MonadDb m) => [String] -> Maybe Platform -> m ()
97 | printCabalFlags = printMany (liftIO . putStrLn <=< (fmap unwords . traverse buildCfgToCabalFlag))
98 |
99 | buildCfgToCabalFlag :: MonadIO m => BuildCfg -> m String
100 | buildCfgToCabalFlag = fmap (("--extra-lib-dirs=" ++) . (> "lib")) . buildCfgToDir
101 |
102 | -- TODO: do something more sophisticated; allow packages to return their own
103 | -- dir?
104 | buildCfgToLinkerFlags :: MonadIO m => BuildCfg -> m String
105 | buildCfgToLinkerFlags = fmap (("-L" ++) . (> "lib")) . buildCfgToDir
106 |
107 | buildCfgToCFlags :: MonadIO m => BuildCfg -> m String
108 | buildCfgToCFlags = fmap (("-I" ++) . (> "include")) . buildCfgToDir
109 |
110 | buildCfgToPkgConfigPath :: MonadIO m => BuildCfg -> m String
111 | buildCfgToPkgConfigPath = fmap (> "lib" > "pkgconfig") . buildCfgToDir
112 |
113 | buildCfgToLibPath :: MonadIO m => BuildCfg -> m String
114 | buildCfgToLibPath = fmap (> "lib") . buildCfgToDir
115 |
116 | buildCfgToIncludePath :: MonadIO m => BuildCfg -> m String
117 | buildCfgToIncludePath = fmap (> "include") . buildCfgToDir
118 |
119 | installedDb :: (MonadIO m, MonadDb m)
120 | => m (S.Set BuildCfg)
121 | installedDb =
122 | _installedPackages <$> memIndex
123 |
124 | packageInstalled :: (MonadIO m, MonadDb m)
125 | => CPkg
126 | -> Maybe TargetTriple
127 | -> Bool
128 | -> BuildVars
129 | -> m Bool
130 | packageInstalled pkg host glob b = do
131 |
132 | packs <- installedDb
133 |
134 | pure $
135 | (pkgToBuildCfg pkg host glob True b `S.member` packs)
136 | || (pkgToBuildCfg pkg host glob False b `S.member` packs)
137 |
138 | lookupPackage :: (MonadIO m, MonadDb m) => String -> Maybe TargetTriple -> m (Maybe BuildCfg)
139 | lookupPackage name host = do
140 |
141 | packs <- installedDb
142 |
143 | let matches = S.filter (\pkg -> buildName pkg == name && targetArch pkg == host) packs
144 |
145 | pure (S.lookupMax matches)
146 |
147 | lookupOrFail :: (MonadIO m, MonadDb m) => String -> Maybe TargetTriple -> m BuildCfg
148 | lookupOrFail name host = do
149 | pk <- lookupPackage name host
150 | case pk of
151 | Just cfg -> pure cfg
152 | Nothing -> notInstalled name
153 |
154 | -- | @since 0.2.3.0
155 | uninstallPkgByName :: (MonadReader Verbosity m, MonadIO m, MonadDb m)
156 | => String
157 | -> Maybe TargetTriple
158 | -> m ()
159 | uninstallPkgByName name host =
160 | uninstallPkg =<< lookupOrFail name host
161 |
162 | uninstallPkg :: (MonadIO m, MonadDb m, MonadReader Verbosity m)
163 | => BuildCfg
164 | -> m ()
165 | uninstallPkg cpkg = do
166 | unregisterPkg cpkg
167 | (liftIO . removeDirectoryRecursive)
168 | =<< buildCfgToDir cpkg
169 |
170 | unregisterPkg :: (MonadIO m, MonadDb m, MonadReader Verbosity m)
171 | => BuildCfg
172 | -> m ()
173 | unregisterPkg buildCfg = do
174 |
175 | putLoud ("Unregistering package " ++ buildName buildCfg ++ "...")
176 |
177 | indexFile <- pkgIndex
178 | indexContents <- memIndex
179 |
180 | let modIndex = over installedPackages (S.delete buildCfg)
181 | newIndex = modIndex indexContents
182 |
183 | modify modIndex
184 |
185 | liftIO $ BSL.writeFile indexFile (encode newIndex)
186 |
187 | -- TODO: replace this with a proper/sensible database
188 | registerPkg :: (MonadIO m, MonadDb m, MonadReader Verbosity m)
189 | => CPkg
190 | -> Maybe TargetTriple
191 | -> Bool -- ^ Globally installed?
192 | -> Bool -- ^ Manually installed?
193 | -> BuildVars
194 | -> m ()
195 | registerPkg cpkg host glob usr b = do
196 |
197 | putDiagnostic ("Registering package " ++ pkgName cpkg ++ "...")
198 |
199 | indexFile <- pkgIndex
200 | indexContents <- memIndex
201 |
202 | let buildCfg = pkgToBuildCfg cpkg host glob usr b
203 | modIndex = over installedPackages (S.insert buildCfg)
204 | newIndex = modIndex indexContents
205 |
206 | modify modIndex
207 |
208 | liftIO $ BSL.writeFile indexFile (encode newIndex)
209 |
210 | pkgToBuildCfg :: CPkg
211 | -> Maybe TargetTriple
212 | -> Bool
213 | -> Bool -- ^ Was this package manually installed?
214 | -> BuildVars
215 | -> BuildCfg
216 | pkgToBuildCfg (CPkg n v _ _ bds ds cCmd bCmd iCmd) host glob usr bVar =
217 | BuildCfg n v (go <$> bds) (go <$> ds) host glob (cCmd bVar) (bCmd bVar) (iCmd bVar) usr -- TODO: fix pinned build deps &c.
218 | where placeholderVersion = Version [0,1,0,0]
219 | go (Dep n' _) = (n', placeholderVersion)
220 |
221 | platformString :: Maybe TargetTriple -> (FilePath -> FilePath -> FilePath)
222 | platformString Nothing = (>)
223 | platformString (Just p) = \x y -> x > show p > y
224 |
225 | buildCfgToDir :: MonadIO m => BuildCfg -> m FilePath
226 | buildCfgToDir buildCfg = do
227 | global' <- globalPkgDir
228 | -- when hashing, pretend everything has was NOT manually installed so they
229 | -- all have the same hash
230 | let hashed = showHex (abs (hash (buildCfg { manual = False}))) mempty
231 | (>) = platformString (targetArch buildCfg)
232 | pure (global' > buildName buildCfg ++ "-" ++ showVersion (buildVersion buildCfg) ++ "-" ++ hashed)
233 |
234 | globDir :: Maybe TargetTriple -> FilePath
235 | globDir Nothing = "/usr/local"
236 | globDir (Just arch') = "/usr" > show arch'
237 |
238 | cPkgToDir :: MonadIO m
239 | => CPkg
240 | -> Maybe TargetTriple
241 | -> Bool
242 | -> BuildVars
243 | -> m FilePath
244 | cPkgToDir pk host False bv = buildCfgToDir (pkgToBuildCfg pk host False undefined bv)
245 | cPkgToDir _ host _ _ = pure (globDir host)
246 |
--------------------------------------------------------------------------------
/dhall/cpkg-prelude.dhall:
--------------------------------------------------------------------------------
1 | {- Dhall prelude imports -}
2 | let concatMapSep =
3 | https://raw.githubusercontent.com/dhall-lang/dhall-lang/9f259cd68870b912fbf2f2a08cd63dc3ccba9dc3/Prelude/Text/concatMapSep sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840
4 |
5 | let concatMapText =
6 | https://raw.githubusercontent.com/dhall-lang/dhall-lang/9f259cd68870b912fbf2f2a08cd63dc3ccba9dc3/Prelude/Text/concatMap sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f
7 |
8 | let concatMap =
9 | https://raw.githubusercontent.com/dhall-lang/dhall-lang/9f259cd68870b912fbf2f2a08cd63dc3ccba9dc3/Prelude/List/concatMap sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64
10 |
11 | let map =
12 | https://raw.githubusercontent.com/dhall-lang/dhall-lang/9f259cd68870b912fbf2f2a08cd63dc3ccba9dc3/Prelude/List/map sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680
13 |
14 | let mapOptional =
15 | https://raw.githubusercontent.com/dhall-lang/dhall-lang/bf757ba1ee526714278568012c6bc98d7ea9757e/Prelude/Optional/map sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa
16 |
17 | let not =
18 | https://raw.githubusercontent.com/dhall-lang/dhall-lang/9f259cd68870b912fbf2f2a08cd63dc3ccba9dc3/Prelude/Bool/not sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4
19 |
20 | let types = ../dhall/cpkg-types.dhall
21 |
22 | let showVersion = concatMapSep "." Natural Natural/show
23 |
24 | let maybeAppend =
25 | λ(a : Type) →
26 | λ(x : Optional a) →
27 | λ(xs : List a) →
28 | merge { Some = λ(x : a) → xs # [ x ], None = xs } x
29 |
30 | let printArch =
31 | λ(arch : types.Arch) →
32 | merge
33 | { X64 = "x86_64"
34 | , AArch = "aarch64"
35 | , Arm = "arm"
36 | , RISCV64 = "riscv64"
37 | , PowerPC = "powerpc"
38 | , PowerPC64 = "powerpc64"
39 | , PowerPC64le = "powerpc64le"
40 | , Sparc64 = "sparc64"
41 | , S390x = "s390x"
42 | , Alpha = "alpha"
43 | , M68k = "m68k"
44 | , Mips = "mips"
45 | , MipsEl = "mipsel"
46 | , Mips64 = "mips64"
47 | , Mips64El = "mips64el"
48 | , X86 = "i686"
49 | , SH4 = "sh4"
50 | , HPPA = "hppa"
51 | , HPPA64 = "hppa64"
52 | , MipsIsa32r6El = "mipsisa32r6el"
53 | , MipsIsa32r6 = "mipsisa32r6"
54 | , MipsIsa64r6El = "mipsisa64r6el"
55 | , MipsIsa64r6 = "mipsisa64r6"
56 | }
57 | arch
58 |
59 | let printManufacturer =
60 | λ(x : types.Manufacturer) →
61 | merge { Unknown = "unknown", Apple = "apple", IBM = "ibm", PC = "pc" } x
62 |
63 | let libSuffix =
64 | λ(os : types.OS) →
65 | merge
66 | { FreeBSD = "so"
67 | , OpenBSD = "so"
68 | , NetBSD = "so"
69 | , Solaris = "so"
70 | , Dragonfly = "so"
71 | , Linux = "so"
72 | , Darwin = "dylib"
73 | , Windows = "dll"
74 | , Redox = "so"
75 | , Haiku = "so"
76 | , IOS = "dylib"
77 | , AIX = "so"
78 | , Hurd = "so"
79 | , Android = "so"
80 | , NoOs = "so"
81 | }
82 | os
83 |
84 | let printOS =
85 | λ(os : types.OS) →
86 | merge
87 | { FreeBSD = "freebsd"
88 | , OpenBSD = "openbsd"
89 | , NetBSD = "netbsd"
90 | , Solaris = "solaris"
91 | , Dragonfly = "dragonfly"
92 | , Linux = "linux"
93 | , Darwin = "darwin"
94 | , Windows = "w64"
95 | , Redox = "redox"
96 | , Haiku = "haiku"
97 | , IOS = "darwin"
98 | , AIX = "aix"
99 | , Hurd = "hurd"
100 | , Android = "android"
101 | , NoOs = "none"
102 | }
103 | os
104 |
105 | let printABI =
106 | λ(os : types.ABI) →
107 | merge
108 | { GNU = "gnu"
109 | , GNUabi64 = "gnuabi64"
110 | , GNUeabi = "gnueabi"
111 | , GNUeabihf = "gnueabihf"
112 | , GNUspe = "gnuspe"
113 | , MinGw = "mingw32"
114 | }
115 | os
116 |
117 | let printTargetTriple =
118 | λ(t : types.TargetTriple) →
119 | "${printArch t.arch}-${printOS t.os}"
120 | ++ merge
121 | { Some = λ(abi : types.ABI) → "-${printABI abi}", None = "" }
122 | t.abi
123 |
124 | let mkHost =
125 | mapOptional
126 | types.TargetTriple
127 | Text
128 | (λ(tgt : types.TargetTriple) → "--host=${printTargetTriple tgt}")
129 |
130 | let makeExe =
131 | λ(os : types.OS) →
132 | merge
133 | { FreeBSD = "gmake"
134 | , OpenBSD = "gmake"
135 | , NetBSD = "gmake"
136 | , Solaris = "gmake"
137 | , Dragonfly = "gmake"
138 | , Linux = "make"
139 | , Darwin = "make"
140 | , Windows = "make"
141 | , Redox = "make"
142 | , Haiku = "make"
143 | , IOS = "make"
144 | , AIX = "make"
145 | , Hurd = "make"
146 | , Android = "make"
147 | , NoOs = "make"
148 | }
149 | os
150 |
151 | let mkExe = λ(x : Text) → types.Command.MakeExecutable { file = x }
152 |
153 | let mkExes = map Text types.Command mkExe
154 |
155 | let writeFile = types.Command.Write
156 |
157 | let patch = λ(x : Text) → types.Command.Patch { patchContents = x }
158 |
159 | let defaultEnv = None (List types.EnvVar)
160 |
161 | let defaultCall =
162 | { arguments = [] : List Text
163 | , environment = defaultEnv
164 | , procDir = None Text
165 | }
166 |
167 | let call = types.Command.Call
168 |
169 | let symlinkBinary = λ(file : Text) → types.Command.SymlinkBinary { file }
170 |
171 | let symlinkManpage = types.Command.SymlinkManpage
172 |
173 | let symlink =
174 | λ(tgt : Text) →
175 | λ(lnk : Text) →
176 | types.Command.Symlink { tgt, linkName = lnk }
177 |
178 | let copyFile =
179 | λ(src : Text) → λ(dest : Text) → types.Command.CopyFile { src, dest }
180 |
181 | let symlinkBinaries = map Text types.Command symlinkBinary
182 |
183 | let symlinkManpages =
184 | map { file : Text, section : Natural } types.Command symlinkManpage
185 |
186 | let isUnix =
187 | λ(os : types.OS) →
188 | merge
189 | { FreeBSD = True
190 | , OpenBSD = True
191 | , NetBSD = True
192 | , Solaris = True
193 | , Dragonfly = True
194 | , Linux = True
195 | , Darwin = True
196 | , Windows = False
197 | , Redox = False
198 | , Haiku = False
199 | , IOS = True
200 | , AIX = True
201 | , Hurd = True
202 | , Android = True
203 | , NoOs = False
204 | }
205 | os
206 |
207 | let isMac =
208 | λ(os : types.OS) →
209 | merge
210 | { FreeBSD = False
211 | , OpenBSD = False
212 | , NetBSD = False
213 | , Solaris = False
214 | , Dragonfly = False
215 | , Linux = False
216 | , Darwin = True
217 | , Windows = False
218 | , Redox = False
219 | , Haiku = False
220 | , IOS = False
221 | , AIX = False
222 | , Hurd = False
223 | , Android = False
224 | , NoOs = False
225 | }
226 | os
227 |
228 | let mkLDFlagsGeneral =
229 | λ(libDirs : List Text) →
230 | λ(linkLibs : List Text) →
231 | λ(cfg : types.BuildVars) →
232 | let flag0 = concatMapSep " " Text (λ(dir : Text) → "-L${dir}") libDirs
233 |
234 | let flag1 = concatMapText Text (λ(dir : Text) → " -l${dir}") linkLibs
235 |
236 | let flag2 =
237 | concatMapText
238 | Text
239 | ( λ(dir : Text) →
240 | if isMac cfg.buildOS then "" else " -Wl,-rpath-link,${dir}"
241 | )
242 | libDirs
243 |
244 | in { var = "LDFLAGS", value = flag0 ++ flag1 ++ flag2 }
245 |
246 | let mkLDFlags =
247 | λ(libDirs : List Text) → mkLDFlagsGeneral libDirs ([] : List Text)
248 |
249 | let mkLDPath =
250 | λ(libDirs : List Text) →
251 | let flag = concatMapSep ":" Text (λ(dir : Text) → dir) libDirs
252 |
253 | in { var = "LD_LIBRARY_PATH", value = flag }
254 |
255 | let mkLDRunPath =
256 | λ(libDirs : List Text) →
257 | let flag = concatMapSep ":" Text (λ(dir : Text) → dir) libDirs
258 |
259 | in { var = "LD_RUN_PATH", value = flag }
260 |
261 | let mkStaPath =
262 | λ(libDirs : List Text) →
263 | let flag = concatMapText Text (λ(dir : Text) → "${dir}:") libDirs
264 |
265 | in { var = "LIBRARY_PATH"
266 | , value = flag ++ "/usr/local/lib:/lib:/usr/lib"
267 | }
268 |
269 | let osCfg =
270 | λ(cfg : types.BuildVars) →
271 | merge
272 | { Some = λ(tgt : types.TargetTriple) → tgt.os, None = cfg.buildOS }
273 | cfg.targetTriple
274 |
275 | let archCfg =
276 | λ(cfg : types.BuildVars) →
277 | merge
278 | { Some = λ(tgt : types.TargetTriple) → tgt.arch
279 | , None = cfg.buildArch
280 | }
281 | cfg.targetTriple
282 |
283 | let mkPerlLib =
284 | λ ( x
285 | : { libDirs : List Text
286 | , perlVersion : List Natural
287 | , cfg : types.BuildVars
288 | }
289 | ) →
290 | let os = x.cfg.buildOS
291 |
292 | let arch = x.cfg.buildArch
293 |
294 | let flag =
295 | concatMapSep
296 | ":"
297 | Text
298 | ( λ(dir : Text) →
299 | "${dir}/site_perl/${showVersion
300 | x.perlVersion}/${printArch
301 | arch}-${printOS
302 | os}/"
303 | )
304 | x.libDirs
305 |
306 | let major =
307 | merge
308 | { Some = Natural/show, None = "" }
309 | (List/head Natural x.perlVersion)
310 |
311 | in { var = "PERL${major}LIB", value = flag }
312 |
313 | let mkIncludePath =
314 | λ(incls : List Text) →
315 | let flag = concatMapSep ":" Text (λ(dir : Text) → dir) incls
316 |
317 | in { var = "C_INCLUDE_PATH", value = flag }
318 |
319 | let mkCFlags =
320 | λ(cfg : types.BuildVars) →
321 | let flag =
322 | concatMapSep " " Text (λ(dir : Text) → "-I${dir}") cfg.includeDirs
323 |
324 | let staFlag = if cfg.static then " -static" else ""
325 |
326 | in { var = "CPPFLAGS", value = flag ++ staFlag }
327 |
328 | let mkPkgConfigVar =
329 | λ(libDirs : List Text) →
330 | let flag =
331 | concatMapSep ":" Text (λ(dir : Text) → "${dir}/pkgconfig") libDirs
332 |
333 | in { var = "PKG_CONFIG_PATH", value = flag }
334 |
335 | let mkXdgDataDirs =
336 | λ(shareDirs : List Text) →
337 | let flag = concatMapSep ":" Text (λ(dir : Text) → dir) shareDirs
338 |
339 | in { var = "XDG_DATA_DIRS", value = flag }
340 |
341 | let mkPathVar =
342 | λ(binDirs : List Text) →
343 | concatMapText Text (λ(dir : Text) → "${dir}:") binDirs
344 |
345 | let unixPath =
346 | λ(binDirs : List Text) →
347 | { var = "PATH"
348 | , value =
349 | mkPathVar binDirs
350 | ++ "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
351 | }
352 |
353 | let defaultPath =
354 | λ(cfg : types.BuildVars) →
355 | if isUnix cfg.buildOS
356 | then [ unixPath cfg.binDirs ] : List types.EnvVar
357 | else [] : List types.EnvVar
358 |
359 | let libPath =
360 | λ(cfg : types.BuildVars) →
361 | if cfg.static then mkStaPath cfg.linkDirs else mkLDPath cfg.linkDirs
362 |
363 | let mkLDPreload =
364 | λ(libs : List Text) →
365 | let flag = concatMapSep " " Text (λ(lib : Text) → lib) libs
366 |
367 | in { var = "LD_PRELOAD", value = flag }
368 |
369 | let mkGuileEnv =
370 | λ(libs : List Text) →
371 | λ(share : List Text) →
372 | let flag0 =
373 | concatMapSep
374 | ":"
375 | Text
376 | (λ(lib : Text) → "${lib}/guile/3.0/site-ccache")
377 | libs
378 |
379 | let flag1 =
380 | concatMapSep
381 | ":"
382 | Text
383 | (λ(dir : Text) → "${dir}/guile/site/3.0")
384 | share
385 |
386 | in [ { var = "GUILE_LOAD_COMPILED_PATH", value = flag0 }
387 | , { var = "GUILE_LOAD_PATH", value = flag1 }
388 | ]
389 |
390 | let configEnv =
391 | λ(linkLibs : List Text) →
392 | λ(cfg : types.BuildVars) →
393 | defaultPath cfg
394 | # [ mkLDFlagsGeneral cfg.linkDirs linkLibs cfg
395 | , mkCFlags cfg
396 | , mkPkgConfigVar (cfg.shareDirs # cfg.linkDirs)
397 | , libPath cfg
398 | , mkLDRunPath cfg.linkDirs
399 | , mkPerlLib
400 | { libDirs = cfg.linkDirs, perlVersion = [ 5, 30, 2 ], cfg }
401 | ]
402 | # mkGuileEnv cfg.linkDirs cfg.shareDirs
403 |
404 | let buildEnv =
405 | λ(cfg : types.BuildVars) →
406 | defaultPath cfg
407 | # [ mkPkgConfigVar (cfg.shareDirs # cfg.linkDirs)
408 | , mkPerlLib
409 | { libDirs = cfg.linkDirs, perlVersion = [ 5, 30, 2 ], cfg }
410 | , mkLDPath cfg.linkDirs
411 | , mkLDFlagsGeneral cfg.linkDirs ([] : List Text) cfg
412 | ]
413 | # mkGuileEnv cfg.linkDirs cfg.shareDirs
414 |
415 | let configSome =
416 | λ(linkLibs : List Text) →
417 | λ(cfg : types.BuildVars) →
418 | Some (configEnv linkLibs cfg)
419 |
420 | let generalConfigure =
421 | λ(envVars : List Text → types.BuildVars → Optional (List types.EnvVar)) →
422 | λ(filename : Text) →
423 | λ(linkLibs : List Text) →
424 | λ(extraFlags : List Text) →
425 | λ(cfg : types.BuildVars) →
426 | let maybeHost = mkHost cfg.targetTriple
427 |
428 | let modifyArgs = maybeAppend Text maybeHost
429 |
430 | let mac = isMac cfg.buildOS
431 |
432 | let modifyProg =
433 | if mac
434 | then λ(x : List Text) → [ "${filename}" ] # x
435 | else λ(x : List Text) → x
436 |
437 | let program = if mac then "sh" else "./${filename}"
438 |
439 | in [ call
440 | ( defaultCall
441 | ⫽ { program
442 | , arguments =
443 | modifyProg
444 | ( modifyArgs [ "--prefix=${cfg.installDir}" ]
445 | # extraFlags
446 | )
447 | , environment = envVars linkLibs cfg
448 | }
449 | )
450 | ]
451 |
452 | let configWithEnv =
453 | λ(envVars : List Text → types.BuildVars → Optional (List types.EnvVar)) →
454 | generalConfigure envVars "configure" ([] : List Text) ([] : List Text)
455 |
456 | let configureWithFlags =
457 | generalConfigure configSome "configure" ([] : List Text)
458 |
459 | let defaultConfigure = configureWithFlags ([] : List Text)
460 |
461 | let configureLinkExtraLibs =
462 | λ(linkLibs : List Text) →
463 | generalConfigure configSome "configure" linkLibs ([] : List Text)
464 |
465 | let mkAclocalPath =
466 | λ(shareDirs : List Text) →
467 | let flag =
468 | concatMapSep
469 | ":"
470 | Text
471 | (λ(dir : Text) → "${dir}/aclocal:${dir}/autoconf")
472 | shareDirs
473 |
474 | in { var = "ACLOCAL_PATH", value = flag }
475 |
476 | let configureMkExesExtraFlags =
477 | λ(x : { bins : List Text, extraFlags : List Text }) →
478 | λ(cfg : types.BuildVars) →
479 | mkExes x.bins # configureWithFlags x.extraFlags cfg
480 |
481 | let configureMkExes =
482 | λ(bins : List Text) →
483 | configureMkExesExtraFlags { bins, extraFlags = [] : List Text }
484 |
485 | let generalBuild =
486 | λ(cpus : types.BuildVars → Natural) →
487 | λ(envs : List types.EnvVar) →
488 | λ(cfg : types.BuildVars) →
489 | [ call
490 | ( defaultCall
491 | ⫽ { program = makeExe cfg.buildOS
492 | , arguments = [ "-j${Natural/show (cpus cfg)}" ]
493 | , environment = Some envs
494 | }
495 | )
496 | ]
497 |
498 | let defaultCpus = λ(cfg : types.BuildVars) → cfg.cpus
499 |
500 | let singleThreaded = λ(_ : types.BuildVars) → 1
501 |
502 | let buildWith = generalBuild defaultCpus
503 |
504 | let defaultBuild = λ(cfg : types.BuildVars) → buildWith (buildEnv cfg) cfg
505 |
506 | let installWith =
507 | λ(envs : List types.EnvVar) →
508 | λ(cfg : types.BuildVars) →
509 | [ call
510 | ( defaultCall
511 | ⫽ { program = makeExe cfg.buildOS
512 | , arguments = [ "install" ]
513 | , environment = Some envs
514 | }
515 | )
516 | ]
517 |
518 | let defaultInstall = λ(cfg : types.BuildVars) → installWith (buildEnv cfg) cfg
519 |
520 | let installWithBinaries =
521 | λ(bins : List Text) →
522 | λ(installVars : types.BuildVars) →
523 | defaultInstall installVars
524 | # ( if not installVars.isCross
525 | then symlinkBinaries bins
526 | else [] : List types.Command
527 | )
528 |
529 | let installWithManpages =
530 | λ(mans : List { file : Text, section : Natural }) →
531 | λ(installVars : types.BuildVars) →
532 | defaultInstall installVars
533 | # ( if not installVars.isCross
534 | then symlinkManpages mans
535 | else [] : List types.Command
536 | )
537 |
538 | let unbounded = λ(x : Text) → { name = x, bound = types.VersionBound.NoBound }
539 |
540 | let lowerBound =
541 | λ(pkg : { name : Text, lower : List Natural }) →
542 | { name = pkg.name
543 | , bound = types.VersionBound.Lower { lower = pkg.lower }
544 | }
545 |
546 | let upperBound =
547 | λ(pkg : { name : Text, upper : List Natural }) →
548 | { name = pkg.name
549 | , bound = types.VersionBound.Upper { upper = pkg.upper }
550 | }
551 |
552 | let defaultPackage =
553 | { configureCommand = defaultConfigure
554 | , buildCommand = defaultBuild
555 | , installCommand = defaultInstall
556 | , pkgBuildDeps = [] : List types.Dep
557 | , pkgDeps = [] : List types.Dep
558 | }
559 |
560 | let simplePackage =
561 | λ(pkg : { name : Text, version : List Natural }) →
562 | defaultPackage
563 | ⫽ { pkgName = pkg.name
564 | , pkgVersion = pkg.version
565 | , pkgSubdir = "${pkg.name}-${showVersion pkg.version}"
566 | }
567 |
568 | let makeGnuExe =
569 | λ(pkg : { name : Text, version : List Natural }) →
570 | simplePackage pkg
571 | ⫽ { pkgUrl =
572 | "https://ftp.gnu.org/gnu/${pkg.name}/${pkg.name}-${showVersion
573 | pkg.version}.tar.xz"
574 | , installCommand = installWithBinaries [ "bin/${pkg.name}" ]
575 | }
576 |
577 | let makeGnuLibrary =
578 | λ(pkg : { name : Text, version : List Natural }) →
579 | simplePackage pkg
580 | ⫽ { pkgUrl =
581 | "https://ftp.gnu.org/pub/gnu/lib${pkg.name}/lib${pkg.name}-${showVersion
582 | pkg.version}.tar.xz"
583 | , pkgSubdir = "lib${pkg.name}-${showVersion pkg.version}"
584 | }
585 |
586 | let createDir = λ(x : Text) → types.Command.CreateDirectory { dir = x }
587 |
588 | let printCMakeOS =
589 | λ(os : types.OS) →
590 | merge
591 | { FreeBSD = "BSD"
592 | , OpenBSD = "BSD"
593 | , NetBSD = "BSD"
594 | , Solaris = "Solaris"
595 | , Dragonfly = "BSD"
596 | , Linux = "Linux"
597 | , Darwin = "Darwin"
598 | , Windows = "Windows"
599 | , Redox = "Redox"
600 | , Haiku = "Haiku"
601 | , IOS = "Darwin"
602 | , AIX = "AIX"
603 | , Hurd = "Hurd"
604 | , Android = "Android"
605 | , NoOs = "Generic"
606 | }
607 | os
608 |
609 | let cmakeConfigureGeneral =
610 | λ(envVars : types.BuildVars → Optional (List types.EnvVar)) →
611 | λ(flags : List Text) →
612 | λ(cfg : types.BuildVars) →
613 | let host =
614 | merge
615 | { Some =
616 | λ(tgt : types.TargetTriple) →
617 | [ "-DCMAKE_C_COMPILER=${printTargetTriple tgt}-gcc"
618 | , "-DCMAKE_CXX_COMPILER=${printTargetTriple tgt}-g++"
619 | ]
620 | , None =
621 | [ "-DCMAKE_C_COMPILER=gcc", "-DCMAKE_CXX_COMPILER=g++" ]
622 | }
623 | cfg.targetTriple
624 |
625 | let system =
626 | merge
627 | { Some =
628 | λ(tgt : types.TargetTriple) →
629 | [ "-DCMAKE_SYSTEM_NAME=${printCMakeOS tgt.os}" ]
630 | , None = [] : List Text
631 | }
632 | cfg.targetTriple
633 |
634 | in [ createDir "build"
635 | , call
636 | { program = "cmake"
637 | , arguments =
638 | [ "../"
639 | , "-DCMAKE_INSTALL_PREFIX:PATH=${cfg.installDir}"
640 | , "-DCMAKE_MAKE_PROGRAM=${makeExe cfg.buildOS}"
641 | ]
642 | # host
643 | # system
644 | # flags
645 | , environment = envVars cfg
646 | , procDir = Some "build"
647 | }
648 | ]
649 |
650 | let cmakeEnv =
651 | λ(cfg : types.BuildVars) →
652 | [ mkPkgConfigVar (cfg.shareDirs # cfg.linkDirs)
653 | , { var = "CMAKE_INCLUDE_PATH"
654 | , value = (mkIncludePath cfg.includeDirs).value
655 | }
656 | , { var = "CMAKE_LIBRARY_PATH", value = (libPath cfg).value }
657 | ]
658 | # defaultPath cfg
659 |
660 | let cmakeSome = λ(cfg : types.BuildVars) → Some (cmakeEnv cfg)
661 |
662 | let cmakeConfigureWithFlags = cmakeConfigureGeneral cmakeSome
663 |
664 | let cmakeConfigure = cmakeConfigureWithFlags ([] : List Text)
665 |
666 | let cmakeConfigureNinja =
667 | λ(cfg : types.BuildVars) →
668 | let host =
669 | merge
670 | { Some =
671 | λ(tgt : types.TargetTriple) →
672 | [ "-DCMAKE_C_COMPILER=${printTargetTriple tgt}-gcc"
673 | , "-DCMAKE_CXX_COMPILER=${printTargetTriple tgt}-g++"
674 | ]
675 | , None = [] : List Text
676 | }
677 | cfg.targetTriple
678 |
679 | let system =
680 | merge
681 | { Some =
682 | λ(tgt : types.TargetTriple) →
683 | [ "-DCMAKE_SYSTEM_NAME=${printCMakeOS tgt.os}" ]
684 | , None = [] : List Text
685 | }
686 | cfg.targetTriple
687 |
688 | in [ createDir "build"
689 | , call
690 | { program = "cmake"
691 | , arguments =
692 | [ "../"
693 | , "-DCMAKE_INSTALL_PREFIX:PATH=${cfg.installDir}"
694 | , "-G"
695 | , "Ninja"
696 | ]
697 | # host
698 | # system
699 | , environment = Some (cmakeEnv cfg)
700 | , procDir = Some "build"
701 | }
702 | ]
703 |
704 | let cmakeBuild =
705 | λ(cfg : types.BuildVars) →
706 | [ call
707 | { program = "cmake"
708 | , arguments =
709 | [ "--build"
710 | , "."
711 | , "--config"
712 | , "Release"
713 | , "--"
714 | , "-j"
715 | , Natural/show cfg.cpus
716 | ]
717 | , environment = Some (cmakeEnv cfg)
718 | , procDir = Some "build"
719 | }
720 | ]
721 |
722 | let cmakeInstall =
723 | λ(cfg : types.BuildVars) →
724 | [ call
725 | { program = "cmake"
726 | , arguments =
727 | [ "--build", ".", "--target", "install", "--config", "Release" ]
728 | , environment = Some (cmakeEnv cfg)
729 | , procDir = Some "build"
730 | }
731 | ]
732 |
733 | let cmakeInstallWithBinaries =
734 | λ(bins : List Text) →
735 | λ(installVars : types.BuildVars) →
736 | cmakeInstall installVars # symlinkBinaries bins
737 |
738 | let cmakePackage =
739 | defaultPackage
740 | ⫽ { configureCommand = cmakeConfigure
741 | , buildCommand = cmakeBuild
742 | , installCommand = cmakeInstall
743 | , pkgBuildDeps = [ unbounded "cmake" ]
744 | }
745 |
746 | let autogenConfigure =
747 | λ(cfg : types.BuildVars) →
748 | [ call
749 | ( defaultCall
750 | ⫽ { program = "./autogen.sh"
751 | , environment = Some
752 | ( [ mkAclocalPath cfg.shareDirs
753 | , mkPkgConfigVar (cfg.shareDirs # cfg.linkDirs)
754 | ]
755 | # defaultPath cfg
756 | )
757 | }
758 | )
759 | ]
760 | # defaultConfigure cfg
761 |
762 | let fullVersion =
763 | λ(x : { version : List Natural, patch : Natural }) →
764 | x.version # [ x.patch ]
765 |
766 | let mkPyPath =
767 | λ(version : List Natural) →
768 | λ(libDirs : List Text) →
769 | let flag =
770 | concatMapSep
771 | ":"
772 | Text
773 | ( λ(dir : Text) →
774 | "${dir}/python${showVersion version}/site-packages"
775 | )
776 | libDirs
777 |
778 | in { var = "PYTHONPATH", value = flag }
779 |
780 | let mkPy3Path = mkPyPath [ 3, 9 ]
781 |
782 | let mesonCfgFile =
783 | λ(cfg : types.BuildVars) →
784 | let prefix =
785 | merge
786 | { Some =
787 | λ(tgt : types.TargetTriple) → "${printTargetTriple tgt}-"
788 | , None = ""
789 | }
790 | cfg.targetTriple
791 |
792 | in ''
793 | [binaries]
794 | ''
795 | ++ ''
796 | c = '${prefix}gcc'
797 | ''
798 | ++ ''
799 | cpp = '${prefix}g++'
800 | ''
801 | ++ ''
802 | ar = '${prefix}ar'
803 | ''
804 | ++ ''
805 | strip = '${prefix}strip'
806 | ''
807 | ++ ''
808 | pkgconfig = 'pkg-config'
809 | ''
810 | ++ ''
811 | [host_machine]
812 | ''
813 | ++ ''
814 | system = '${printOS (osCfg cfg)}'
815 | ''
816 | ++ ''
817 | cpu_family = '${printArch (archCfg cfg)}'
818 | ''
819 | ++ ''
820 | cpu = '${printArch (archCfg cfg)}'
821 | ''
822 | ++ "endian = 'little'"
823 |
824 | let mesonEnv =
825 | λ(cfg : types.BuildVars) →
826 | Some
827 | ( [ mkPkgConfigVar (cfg.linkDirs # cfg.shareDirs)
828 | , mkPy3Path cfg.linkDirs
829 | , libPath cfg
830 | , mkLDRunPath cfg.linkDirs
831 | , mkLDFlags cfg.linkDirs cfg
832 | , mkCFlags cfg
833 | , mkLDPreload cfg.preloadLibs
834 | ]
835 | # defaultPath cfg
836 | )
837 |
838 | let mesonConfigureGeneral =
839 | λ(envs : types.BuildVars → Optional (List types.EnvVar)) →
840 | λ(flags : List Text) →
841 | λ(cfg : types.BuildVars) →
842 | let crossArgs =
843 | if cfg.isCross
844 | then [ "--cross-file", "cross.txt" ]
845 | else [] : List Text
846 |
847 | in [ createDir "build"
848 | , writeFile
849 | { file = "build/cross.txt", contents = mesonCfgFile cfg }
850 | , call
851 | { program = "meson"
852 | , arguments =
853 | [ "--prefix=${cfg.installDir}", ".." ] # crossArgs # flags
854 | , environment = envs cfg
855 | , procDir = Some "build"
856 | }
857 | ]
858 |
859 | let mesonConfigureWithFlags = mesonConfigureGeneral mesonEnv
860 |
861 | let mesonConfigure = mesonConfigureWithFlags ([] : List Text)
862 |
863 | let ninjaBuildWith =
864 | λ(linkLibs : List Text) →
865 | λ(cfg : types.BuildVars) →
866 | let ldPreload =
867 | if cfg.isCross
868 | then [] : List types.EnvVar
869 | else [ mkLDPreload cfg.preloadLibs ]
870 |
871 | in [ call
872 | ( defaultCall
873 | ⫽ { program = "ninja"
874 | , environment = Some
875 | ( [ mkPkgConfigVar cfg.linkDirs
876 | , mkPy3Path cfg.linkDirs
877 | , libPath cfg
878 | , mkLDRunPath cfg.linkDirs
879 | , mkLDFlagsGeneral cfg.linkDirs linkLibs cfg
880 | , mkCFlags cfg
881 | ]
882 | # defaultPath cfg
883 | # ldPreload
884 | )
885 | , procDir = Some "build"
886 | }
887 | )
888 | ]
889 |
890 | let ninjaBuild = ninjaBuildWith ([] : List Text)
891 |
892 | let ninjaInstall =
893 | λ(cfg : types.BuildVars) →
894 | [ call
895 | ( defaultCall
896 | ⫽ { program = "ninja"
897 | , environment = Some
898 | ( [ mkPkgConfigVar cfg.linkDirs
899 | , mkPy3Path cfg.linkDirs
900 | , libPath cfg
901 | , mkLDRunPath cfg.linkDirs
902 | , mkLDFlags cfg.linkDirs cfg
903 | , mkCFlags cfg
904 | ]
905 | # defaultPath cfg
906 | )
907 | , arguments = [ "install" ]
908 | , procDir = Some "build"
909 | }
910 | )
911 | ]
912 |
913 | let ninjaPackage =
914 | λ(x : { name : Text, version : List Natural }) →
915 | simplePackage x
916 | ⫽ { configureCommand = mesonConfigure
917 | , buildCommand = ninjaBuild
918 | , installCommand = ninjaInstall
919 | , pkgBuildDeps = [ unbounded "meson", unbounded "ninja" ]
920 | }
921 |
922 | let copyFiles =
923 | map { src : Text, dest : Text } types.Command types.Command.CopyFile
924 |
925 | let ninjaInstallWithPkgConfig =
926 | λ(fs : List { src : Text, dest : Text }) →
927 | λ(cfg : types.BuildVars) →
928 | ninjaInstall cfg # copyFiles fs
929 |
930 | let doNothing = λ(_ : types.BuildVars) → [] : List types.Command
931 |
932 | let mesonMoves =
933 | map
934 | Text
935 | { src : Text, dest : Text }
936 | ( λ(pcFile : Text) →
937 | { src = "build/meson-private/${pcFile}"
938 | , dest = "lib/pkgconfig/${pcFile}"
939 | }
940 | )
941 |
942 | let pythonBuild =
943 | λ(version : List Natural) →
944 | λ(cfg : types.BuildVars) →
945 | let major =
946 | merge
947 | { Some = Natural/show, None = "" }
948 | (List/head Natural version)
949 |
950 | let versionString = showVersion version
951 |
952 | in [ createDir
953 | "${cfg.installDir}/lib/python${versionString}/site-packages"
954 | , call
955 | ( defaultCall
956 | ⫽ { program = "python${major}"
957 | , arguments = [ "setup.py", "build" ]
958 | , environment = Some
959 | ( [ { var = "PYTHONPATH"
960 | , value =
961 | "${cfg.installDir}/lib/python${versionString}/site-packages"
962 | }
963 | , mkPkgConfigVar cfg.linkDirs
964 | , libPath cfg
965 | ]
966 | # defaultPath cfg
967 | )
968 | }
969 | )
970 | ]
971 |
972 | let pythonInstall =
973 | λ(version : List Natural) →
974 | λ(cfg : types.BuildVars) →
975 | let major =
976 | merge
977 | { Some = Natural/show, None = "" }
978 | (List/head Natural version)
979 |
980 | let versionString = showVersion version
981 |
982 | in [ createDir
983 | "${cfg.installDir}/lib/python${versionString}/site-packages"
984 | , call
985 | ( defaultCall
986 | ⫽ { program = "python${major}"
987 | , arguments =
988 | [ "setup.py"
989 | , "install"
990 | , "--prefix=${cfg.installDir}"
991 | , "--optimize=1"
992 | ]
993 | , environment = Some
994 | ( [ { var = "PYTHONPATH"
995 | , value =
996 | "${cfg.installDir}/lib/python${versionString}/site-packages"
997 | }
998 | , mkPkgConfigVar cfg.linkDirs
999 | , libPath cfg
1000 | ]
1001 | # defaultPath cfg
1002 | )
1003 | }
1004 | )
1005 | ]
1006 |
1007 | let pythonPackage =
1008 | λ(pyVersion : List Natural) →
1009 | λ(x : { name : Text, version : List Natural }) →
1010 | let major =
1011 | merge
1012 | { Some = Natural/show, None = "" }
1013 | (List/head Natural pyVersion)
1014 |
1015 | in simplePackage x
1016 | ⫽ { configureCommand = doNothing
1017 | , buildCommand = pythonBuild pyVersion
1018 | , installCommand = pythonInstall pyVersion
1019 | , pkgBuildDeps = [ unbounded "python${major}" ]
1020 | }
1021 |
1022 | let python3Build = pythonBuild [ 3, 9 ]
1023 |
1024 | let python3Install = pythonInstall [ 3, 9 ]
1025 |
1026 | let python3Package = pythonPackage [ 3, 9 ]
1027 |
1028 | let python2Package = pythonPackage [ 2, 7 ]
1029 |
1030 | let mkCCVar =
1031 | λ(cfg : types.BuildVars) →
1032 | merge
1033 | { Some =
1034 | λ(tgt : types.TargetTriple) →
1035 | [ { var = "CC", value = "${printTargetTriple tgt}-gcc" } ]
1036 | , None = [] : List types.EnvVar
1037 | }
1038 | cfg.targetTriple
1039 |
1040 | let squishVersion = concatMapText Natural Natural/show
1041 |
1042 | let mkCCArg =
1043 | λ(cfg : types.BuildVars) →
1044 | merge
1045 | { Some =
1046 | λ(tgt : types.TargetTriple) →
1047 | [ "CC=${printTargetTriple tgt}-gcc" ]
1048 | , None = [] : List Text
1049 | }
1050 | cfg.targetTriple
1051 |
1052 | let mkFRCArg =
1053 | λ(cfg : types.BuildVars) →
1054 | merge
1055 | { Some =
1056 | λ(tgt : types.TargetTriple) →
1057 | [ "CC=${printTargetTriple tgt}-gcc" ]
1058 | , None = [] : List Text
1059 | }
1060 | cfg.targetTriple
1061 |
1062 | let preloadEnv =
1063 | λ(_ : List Text) →
1064 | λ(cfg : types.BuildVars) →
1065 | Some
1066 | ( defaultPath cfg
1067 | # [ mkLDFlags cfg.linkDirs cfg
1068 | , mkCFlags cfg
1069 | , mkPkgConfigVar cfg.linkDirs
1070 | , libPath cfg
1071 | , mkXdgDataDirs cfg.shareDirs
1072 | , mkLDPreload cfg.preloadLibs
1073 | , mkPerlLib
1074 | { libDirs = cfg.linkDirs, perlVersion = [ 5, 30, 2 ], cfg }
1075 | ]
1076 | )
1077 |
1078 | let perlConfigure =
1079 | λ(cfg : types.BuildVars) →
1080 | [ call
1081 | { program = "perl"
1082 | , arguments = [ "Makefile.PL", "PREFIX=${cfg.installDir}" ]
1083 | , environment = preloadEnv ([] : List Text) cfg
1084 | , procDir = None Text
1085 | }
1086 | ]
1087 |
1088 | let preloadCfg =
1089 | generalConfigure preloadEnv "configure" ([] : List Text) ([] : List Text)
1090 |
1091 | let printEnvVar = λ(var : types.EnvVar) → "${var.var}=${var.value}"
1092 |
1093 | let mkPyWrapper =
1094 | λ(version : List Natural) →
1095 | λ(binName : Text) →
1096 | λ(cfg : types.BuildVars) →
1097 | let wrapperContents =
1098 | "${printEnvVar
1099 | ( libPath cfg
1100 | )} ${printEnvVar
1101 | ( mkPyPath version cfg.linkDirs
1102 | )}:${cfg.installDir}/lib/python${showVersion
1103 | version}/site-packages ${cfg.installDir}/bin/${binName} \$@"
1104 |
1105 | let wrapped = "wrapper/${binName}"
1106 |
1107 | in [ createDir "wrapper"
1108 | , writeFile { file = wrapped, contents = wrapperContents }
1109 | , mkExe wrapped
1110 | , copyFile wrapped wrapped
1111 | , symlinkBinary wrapped
1112 | ]
1113 |
1114 | let mkPy3Wrapper = mkPyWrapper [ 3, 9 ]
1115 |
1116 | let mkPy2Wrapper = mkPyWrapper [ 2, 7 ]
1117 |
1118 | let installWithPyWrappers =
1119 | λ(version : List Natural) →
1120 | λ(binNames : List Text) →
1121 | λ(cfg : types.BuildVars) →
1122 | pythonInstall version cfg
1123 | # concatMap
1124 | Text
1125 | types.Command
1126 | (λ(bin : Text) → mkPyWrapper version bin cfg)
1127 | binNames
1128 |
1129 | let installWithPy3Wrappers = installWithPyWrappers [ 3, 9 ]
1130 |
1131 | let mkLDPathWrapper =
1132 | λ(cfg : types.BuildVars) →
1133 | λ(binName : Text) →
1134 | let wrapper =
1135 | "${printEnvVar
1136 | ( mkLDPath cfg.linkDirs
1137 | )}:${cfg.installDir}/lib LD_PRELOAD='${( mkLDPreload
1138 | cfg.preloadLibs
1139 | ).value}' ${cfg.installDir}/bin/${binName} \$@"
1140 |
1141 | let wrapped = "wrapper/${binName}"
1142 |
1143 | in [ createDir "wrapper"
1144 | , writeFile { file = wrapped, contents = wrapper }
1145 | , mkExe wrapped
1146 | , copyFile wrapped wrapped
1147 | , symlinkBinary wrapped
1148 | ]
1149 |
1150 | let mkLDPathWrappers =
1151 | λ(cfg : types.BuildVars) →
1152 | λ(bins : List Text) →
1153 | concatMap
1154 | Text
1155 | types.Command
1156 | (λ(bin : Text) → mkLDPathWrapper cfg bin)
1157 | bins
1158 |
1159 | let installWithWrappers =
1160 | λ(bins : List Text) →
1161 | λ(cfg : types.BuildVars) →
1162 | defaultInstall cfg # mkLDPathWrappers cfg bins
1163 |
1164 | let underscoreVersion = concatMapSep "_" Natural Natural/show
1165 |
1166 | let isX64 =
1167 | λ(arch : types.Arch) →
1168 | merge
1169 | { X64 = True
1170 | , AArch = False
1171 | , Arm = False
1172 | , RISCV64 = False
1173 | , PowerPC = False
1174 | , PowerPC64 = False
1175 | , PowerPC64le = False
1176 | , Sparc64 = False
1177 | , S390x = False
1178 | , Alpha = False
1179 | , M68k = False
1180 | , Mips = False
1181 | , MipsEl = False
1182 | , Mips64 = False
1183 | , Mips64El = False
1184 | , X86 = False
1185 | , SH4 = False
1186 | , HPPA = False
1187 | , HPPA64 = False
1188 | , MipsIsa32r6El = False
1189 | , MipsIsa32r6 = False
1190 | , MipsIsa64r6El = False
1191 | , MipsIsa64r6 = False
1192 | }
1193 | arch
1194 |
1195 | let configureWithPatches =
1196 | λ(patches : List Text) →
1197 | λ(cfg : types.BuildVars) →
1198 | map Text types.Command (λ(p : Text) → patch p) patches
1199 | # defaultConfigure cfg
1200 |
1201 | let configureWithPatch = λ(p : Text) → configureWithPatches [ p ]
1202 |
1203 | let installPrefix =
1204 | λ(cfg : types.BuildVars) →
1205 | [ call
1206 | ( defaultCall
1207 | ⫽ { program = "make"
1208 | , arguments =
1209 | [ "prefix=${cfg.installDir}"
1210 | , "PREFIX=${cfg.installDir}"
1211 | , "install"
1212 | ]
1213 | , environment = Some (buildEnv cfg)
1214 | }
1215 | )
1216 | ]
1217 |
1218 | in { showVersion
1219 | , makeGnuLibrary
1220 | , makeGnuExe
1221 | , defaultPackage
1222 | , unbounded
1223 | , lowerBound
1224 | , upperBound
1225 | , makeExe
1226 | , printArch
1227 | , printManufacturer
1228 | , printOS
1229 | , printTargetTriple
1230 | , call
1231 | , mkExe
1232 | , mkExes
1233 | , createDir
1234 | , mkHost
1235 | , defaultConfigure
1236 | , defaultBuild
1237 | , defaultInstall
1238 | , cmakeConfigure
1239 | , cmakeConfigureGeneral
1240 | , cmakeConfigureWithFlags
1241 | , cmakeBuild
1242 | , cmakeInstall
1243 | , cmakePackage
1244 | , autogenConfigure
1245 | , defaultCall
1246 | , defaultEnv
1247 | , maybeAppend
1248 | , mkCFlags
1249 | , mkLDFlags
1250 | , mkLDFlagsGeneral
1251 | , mkLDPath
1252 | , mkLDRunPath
1253 | , mkStaPath
1254 | , libPath
1255 | , mkPyPath
1256 | , mkPy3Path
1257 | , mkIncludePath
1258 | , isUnix
1259 | , defaultPath
1260 | , simplePackage
1261 | , symlinkBinary
1262 | , symlinkManpage
1263 | , symlink
1264 | , symlinkBinaries
1265 | , symlinkManpages
1266 | , installWithBinaries
1267 | , installWithManpages
1268 | , configureMkExes
1269 | , generalConfigure
1270 | , configureWithFlags
1271 | , configureMkExesExtraFlags
1272 | , writeFile
1273 | , cmakeInstallWithBinaries
1274 | , copyFile
1275 | , mkPathVar
1276 | , mkPkgConfigVar
1277 | , fullVersion
1278 | , mesonConfigure
1279 | , mesonConfigureGeneral
1280 | , mesonEnv
1281 | , mesonConfigureWithFlags
1282 | , ninjaBuild
1283 | , ninjaInstall
1284 | , ninjaInstallWithPkgConfig
1285 | , ninjaPackage
1286 | , doNothing
1287 | , perlConfigure
1288 | , copyFiles
1289 | , mkPerlLib
1290 | , mesonMoves
1291 | , python3Build
1292 | , python3Install
1293 | , python3Package
1294 | , mkLDPreload
1295 | , configureLinkExtraLibs
1296 | , mkXdgDataDirs
1297 | , buildWith
1298 | , installWith
1299 | , mkCCVar
1300 | , squishVersion
1301 | , osCfg
1302 | , archCfg
1303 | , mkCCArg
1304 | , mkFRCArg
1305 | , mesonCfgFile
1306 | , python2Package
1307 | , configEnv
1308 | , configSome
1309 | , preloadEnv
1310 | , preloadCfg
1311 | , printEnvVar
1312 | , mkPyWrapper
1313 | , mkPy3Wrapper
1314 | , mkPy2Wrapper
1315 | , installWithPyWrappers
1316 | , installWithPy3Wrappers
1317 | , cmakeConfigureNinja
1318 | , mkLDPathWrapper
1319 | , mkLDPathWrappers
1320 | , installWithWrappers
1321 | , cmakeEnv
1322 | , cmakeSome
1323 | , underscoreVersion
1324 | , isX64
1325 | , configWithEnv
1326 | , buildEnv
1327 | , patch
1328 | , mkAclocalPath
1329 | , configureWithPatches
1330 | , configureWithPatch
1331 | , installPrefix
1332 | , unixPath
1333 | , generalBuild
1334 | , defaultCpus
1335 | , singleThreaded
1336 | , libSuffix
1337 | }
1338 |
--------------------------------------------------------------------------------