1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
-----------------------------------------------------------------------------
-- |
-- Module : Hadrian.Package
-- Copyright : (c) Andrey Mokhov 2014-2017
-- License : MIT (see the file LICENSE)
-- Maintainer : andrey.mokhov@gmail.com
-- Stability : experimental
--
-- A /package/ is a collection of files. We currently only support C and Haskell
-- packages and treat a package as either a library or a program. The latter is
-- a gross oversimplification as, for example, Haskell packages can be both.
-- This works for now, but should be improved in future.
-----------------------------------------------------------------------------
module Hadrian.Package (
-- * Data types
Package (..), PackageName, PackageType,
-- * Construction and properties
library, program, dummyPackage, isLibrary, isProgram,
-- * Package directory structure
pkgCabalFile
) where
import Development.Shake.Classes
import Development.Shake.FilePath
import GHC.Generics
import Hadrian.Utilities
-- TODO: Make PackageType more precise.
-- See https://github.com/snowleopard/hadrian/issues/12.
data PackageType = Library | Program deriving (Eq, Generic, Ord, Show)
type PackageName = String
-- TODO: Consider turning Package into a GADT indexed with language and type.
data Package = Package {
-- | The package type. 'Library' and 'Program' packages are supported.
pkgType :: PackageType,
-- | The package name. We assume that all packages have different names,
-- hence two packages with the same name are considered equal.
pkgName :: PackageName,
-- | The path to the package source code relative to the root of the build
-- system. For example, @libraries/Cabal/Cabal@ and @ghc@ are paths to the
-- @Cabal@ and @ghc-bin@ packages in GHC.
pkgPath :: FilePath
} deriving (Eq, Generic, Ord, Show)
-- | Construct a library package.
library :: PackageName -> FilePath -> Package
library = Package Library
-- | Construct a program package.
program :: PackageName -> FilePath -> Package
program = Package Program
-- TODO: Remove this hack.
-- | A dummy package that we never try to build but use when we need a 'Package'
-- to construct a 'Context' but do not need to access the package field.
dummyPackage :: Package
dummyPackage = library "dummy" "dummy/path/"
-- | Is this a library package?
isLibrary :: Package -> Bool
isLibrary (Package Library _ _) = True
isLibrary _ = False
-- | Is this a program package?
isProgram :: Package -> Bool
isProgram (Package Program _ _) = True
isProgram _ = False
-- | The path to the Cabal file of a Haskell package, e.g. @ghc/ghc-bin.cabal@.
pkgCabalFile :: Package -> FilePath
pkgCabalFile p = pkgPath p -/- pkgName p <.> "cabal"
instance Binary PackageType
instance Hashable PackageType
instance NFData PackageType
instance Binary Package
instance Hashable Package
instance NFData Package
|