240b85d9945328ff711ef3a0ae12ebcc95bf481f
[ghc.git] / src / Package.hs
1 {-# LANGUAGE DeriveGeneric, GeneralizedNewtypeDeriving #-}
2
3 module Package (
4 Package (..), PackageName (..), PackageType (..),
5 -- * Queries
6 pkgNameString,
7 pkgCabalFile,
8 matchPackageNames,
9 -- * Helpers for constructing and using 'Package's
10 setPath, topLevel, library, utility, setType, isLibrary, isProgram
11 ) where
12
13 import Data.String
14 import GHC.Generics (Generic)
15
16 import Base
17
18 -- | The name of a Cabal package
19 newtype PackageName = PackageName { fromPackageName :: String }
20 deriving (Eq, Ord, IsString, Generic, Binary, Hashable, Typeable, NFData)
21
22 -- TODO: Make PackageType more precise, #12
23 -- TODO: Turn Program to Program FilePath thereby getting rid of programPath
24 -- | We regard packages as either being libraries or programs. This is
25 -- bit of a convenient lie as Cabal packages can be both, but it works
26 -- for now.
27 data PackageType = Program | Library deriving Generic
28
29 data Package = Package
30 { pkgName :: PackageName -- ^ Examples: "ghc", "Cabal"
31 , pkgPath :: FilePath -- ^ pkgPath is the path to the source code relative to the root.
32 -- e.g. "compiler", "libraries/Cabal/Cabal"
33 , pkgType :: PackageType
34 } deriving Generic
35
36 -- | Prettyprint Package name.
37 pkgNameString :: Package -> String
38 pkgNameString = fromPackageName . pkgName
39
40 -- | Relative path to cabal file, e.g.: "libraries/Cabal/Cabal/Cabal.cabal"
41 pkgCabalFile :: Package -> FilePath
42 pkgCabalFile pkg = pkgPath pkg -/- pkgNameString pkg <.> "cabal"
43
44 -- | Smart constructor for a top-level package, e.g. 'compiler'.
45 topLevel :: PackageName -> Package
46 topLevel name = Package name (fromPackageName name) Library
47
48 -- | Smart constructor for a library package, e.g. 'array'.
49 library :: PackageName -> Package
50 library name = Package name ("libraries" -/- fromPackageName name) Library
51
52 -- | Smart constructor for a utility package, e.g. 'haddock'.
53 utility :: PackageName -> Package
54 utility name = Package name ("utils" -/- fromPackageName name) Program
55
56 -- | Amend package path. Useful when a package name doesn't match its path.
57 setPath :: Package -> FilePath -> Package
58 setPath pkg path = pkg { pkgPath = path }
59
60 -- | Amend package type.
61 setType :: Package -> PackageType -> Package
62 setType pkg ty = pkg { pkgType = ty }
63
64 -- | Check whether a package is a library.
65 isLibrary :: Package -> Bool
66 isLibrary (Package _ _ Library) = True
67 isLibrary _ = False
68
69 -- | Check whether a package is a program.
70 isProgram :: Package -> Bool
71 isProgram (Package _ _ Program) = True
72 isProgram _ = False
73
74 -- TODO: Get rid of non-derived Show instances.
75 instance Show Package where
76 show = pkgNameString
77
78 instance Eq Package where
79 (==) = (==) `on` pkgName
80
81 instance Ord Package where
82 compare = compare `on` pkgName
83
84 -- | Given a sorted list of packages and a sorted list of package names, returns
85 -- packages whose names appear in the list of names.
86 matchPackageNames :: [Package] -> [PackageName] -> [Package]
87 matchPackageNames = intersectOrd (\pkg name -> compare (pkgName pkg) name)
88
89 -- Instances for storing in the Shake database
90 instance Binary Package
91 instance Hashable Package where
92 hashWithSalt salt = hashWithSalt salt . show
93 instance NFData Package
94
95 instance Binary PackageType
96 instance Hashable PackageType
97 instance NFData PackageType