Implement "build-tool-depends" in Cabal, and legacy "build-tools" via desugar
[cabal.git] / Cabal / Distribution / Simple / BuildToolDepends.hs
blob9912e747f1bff58290ee68fe1aa93187a4c171b5
1 -- |
2 --
3 -- This modules provides functions for working with both the legacy
4 -- "build-tools" field, and its replacement, "build-tool-depends". Prefer using
5 -- the functions contained to access those fields directly.
6 module Distribution.Simple.BuildToolDepends where
8 import Data.Maybe
9 import qualified Data.Map as Map
11 import Distribution.Package
12 import Distribution.PackageDescription
13 import Distribution.Types.ExeDependency
14 import Distribution.Types.LegacyExeDependency
15 import Distribution.Types.UnqualComponentName
17 -- | Desugar a "build-tools" entry into proper a executable dependency if
18 -- possible.
20 -- An entry can be so desguared in two cases:
22 -- 1. The name in build-tools matches a locally defined executable. The
23 -- executable dependency produced is on that exe in the current package.
25 -- 2. The name in build-tools matches a hard-coded set of known tools. For now,
26 -- the executable dependency produced is one an executable in a package of
27 -- the same, but the hard-coding could just as well be per-key.
29 -- The first cases matches first.
30 desugarBuildTool :: PackageDescription
31 -> LegacyExeDependency
32 -> Maybe ExeDependency
33 desugarBuildTool pkg led =
34 if foundLocal
35 then Just $ ExeDependency (packageName pkg) toolName reqVer
36 else Map.lookup name whiteMap
37 where
38 LegacyExeDependency name reqVer = led
39 toolName = mkUnqualComponentName name
40 foundLocal = toolName `elem` map exeName (executables pkg)
41 whitelist = [ "hscolour", "haddock", "happy", "alex", "hsc2hs", "c2hs"
42 , "cpphs", "greencard"]
43 whiteMap = Map.fromList $ flip map whitelist $ \n ->
44 (n, ExeDependency (mkPackageName n) (mkUnqualComponentName n) reqVer)
46 -- | Get everything from "build-tool-depends", along with entries from
47 -- "build-tools" that we know how to desugar.
49 -- This should almost always be used instead of just accessing the
50 -- `toolDepends` field directly.
51 getAllToolDependencies :: PackageDescription
52 -> BuildInfo
53 -> [ExeDependency]
54 getAllToolDependencies pkg bi =
55 toolDepends bi ++ mapMaybe (desugarBuildTool pkg) (buildTools bi)
57 -- | Does the given executable dependency map to this current package?
59 -- This is a tiny function, but used in a number of places.
61 -- This function is only sound to call on `BuildInfo`s from the given package
62 -- description. This is because it just filters the package names of each
63 -- dependency, and does not check whether version bounds in fact exclude the
64 -- current package, or the referenced components in fact exist in the current
65 -- package.
67 -- This is OK because when a package is loaded, it is checked (in
68 -- `Distribution.Package.Check`) that dependencies matching internal components
69 -- do indeed have version bounds accepting the current package, and any
70 -- depended-on component in the current package actually exists. In fact this
71 -- check is performed by gathering the internal tool dependencies of each
72 -- component of the package according to this module, and ensuring those
73 -- properties on each so-gathered dependency.
75 -- version bounds and components of the package are unchecked. This is because
76 -- we sanitize exe deps so that the matching name implies these other
77 -- conditions.
78 isInternal :: PackageDescription -> ExeDependency -> Bool
79 isInternal pkg (ExeDependency n _ _) = n == packageName pkg
82 -- | Get internal "build-tool-depends", along with internal "build-tools"
84 -- This is a tiny function, but used in a number of places. The same
85 -- restrictions that apply to `isInternal` also apply to this function.
86 getAllInternalToolDependencies :: PackageDescription
87 -> BuildInfo
88 -> [ExeDependency]
89 getAllInternalToolDependencies pkg bi =
90 filter (isInternal pkg) $ getAllToolDependencies pkg bi