Skip to content

Commit d9bf678

Browse files
committed
Per-component new-build support (no Custom support yet).
A bit of a megapatch. Here's what's in it: * First, a few miscellaneous utility functions and reexports in Cabal. I could have split these into a separate commit but I was too lazy to. * Distribution.Client.Install got refactored: instead of using PackageFixedDeps, it uses IsUnit instead. This is because we weren't using ComponentDeps in a nontrivial way; we just need some graph structure and IsNode (with UnitId keys) fulfills that. I also removed the invariant checking and error reporting because it was being annoying (we check the invariants already in SolverInstallPlan). * Look at Distribution.Client.ProjectPlanning.Types. This contains the primary type change: ElaboratedConfiguredPackage is now EITHER a monolithic ElaboratedPackage, or a per-component ElaboratedComponent (it should get renamed but I didn't do that in this patch.) These are what we're going to store in our plans: if a package we're building has a Setup script which supports per-component builds, we'll explode it into a component. Otherwise we'll keep it as a package. We'll see codepaths for both throughout. * OK, so the expansion happens in ProjectPlanning, mostly in 'elaborateAndExpandSolverPackage'. You should review the package hash computation code closely. When we can separate components, we compute a hash for each INDEPENDENTLY. This is good: we get more sharing. * We need to adjust the target resolution and pruning code in ProjectOrchestration and ProjectPlanning. I did a dumb but easy idea: if a user mentions 'packagename' in a target name, I spray the PackageTarget on every possibly relevant IPID in buildTargets', and then pare it down later. * And of course there's code in ProjectBuilding to actual do a configure and then build. * We change the layout of build directories so that we can track each component separately. While I was doing that, I also added compiler and platform information. Custom doesn't work yet because I need to give them their own separate component, and teach Cabal how to build them specially. Signed-off-by: Edward Z. Yang <[email protected]>
1 parent e6b6167 commit d9bf678

File tree

28 files changed

+996
-472
lines changed

28 files changed

+996
-472
lines changed

Cabal/Distribution/Package.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ module Distribution.Package (
2727
UnitId(..),
2828
mkUnitId,
2929
mkLegacyUnitId,
30+
unitIdComponentId,
3031
getHSLibraryName,
3132
InstalledPackageId, -- backwards compat
3233

@@ -176,6 +177,10 @@ mkUnitId = SimpleUnitId . ComponentId
176177
mkLegacyUnitId :: PackageId -> UnitId
177178
mkLegacyUnitId = SimpleUnitId . ComponentId . display
178179

180+
-- | Extract 'ComponentId' from 'UnitId'.
181+
unitIdComponentId :: UnitId -> ComponentId
182+
unitIdComponentId (SimpleUnitId cid) = cid
183+
179184
-- ------------------------------------------------------------
180185
-- * Package source dependencies
181186
-- ------------------------------------------------------------

Cabal/Distribution/Simple/Configure.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ module Distribution.Simple.Configure (configure,
3535
tryGetPersistBuildConfig,
3636
maybeGetPersistBuildConfig,
3737
findDistPref, findDistPrefOrDefault,
38+
mkComponentsGraph,
39+
getInternalPackages,
3840
computeComponentId,
3941
computeCompatPackageKey,
4042
computeCompatPackageName,

Cabal/Distribution/Types/ComponentEnabledSpec.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ data ComponentEnabledSpec
5454
= ComponentEnabledSpec { testsEnabled :: Bool,
5555
benchmarksEnabled :: Bool }
5656
| OneComponentEnabledSpec ComponentName
57-
deriving (Generic, Read, Show)
57+
deriving (Generic, Read, Show, Eq)
5858
instance Binary ComponentEnabledSpec
5959

6060
-- | The default set of enabled components. Historically tests and

Cabal/Distribution/Types/PackageDescription.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ module Distribution.Types.PackageDescription (
4343
updatePackageDescription,
4444
pkgComponents,
4545
pkgBuildableComponents,
46+
enabledComponents,
4647
lookupComponent,
4748
getComponent,
4849
) where
@@ -57,6 +58,7 @@ import Distribution.Types.Benchmark
5758

5859
import Distribution.Types.Component
5960
import Distribution.Types.ComponentName
61+
import Distribution.Types.ComponentEnabledSpec
6062
import Distribution.Types.SetupBuildInfo
6163
import Distribution.Types.BuildInfo
6264
import Distribution.Types.BuildType
@@ -346,6 +348,13 @@ pkgComponents pkg =
346348
pkgBuildableComponents :: PackageDescription -> [Component]
347349
pkgBuildableComponents = filter componentBuildable . pkgComponents
348350

351+
-- | A list of all components in the package that are enabled.
352+
--
353+
-- @since 2.0.0.0
354+
--
355+
enabledComponents :: PackageDescription -> ComponentEnabledSpec -> [Component]
356+
enabledComponents pkg enabled = filter (componentEnabled enabled) $ pkgBuildableComponents pkg
357+
349358
lookupComponent :: PackageDescription -> ComponentName -> Maybe Component
350359
lookupComponent pkg CLibName = fmap CLib (library pkg)
351360
lookupComponent pkg (CSubLibName name) =

cabal-install/Distribution/Client/CmdBuild.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ buildAction (configFlags, configExFlags, installFlags, haddockFlags)
6363
-- repl targets (as opposed to say repl or haddock targets).
6464
selectBuildTargets =
6565
selectTargets
66+
verbosity
6667
BuildDefaultComponents
6768
BuildSpecificComponent
6869

cabal-install/Distribution/Client/CmdFreeze.hs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ module Distribution.Client.CmdFreeze (
77
) where
88

99
import Distribution.Client.ProjectPlanning
10-
( ElaboratedInstallPlan, rebuildInstallPlan )
1110
import Distribution.Client.ProjectConfig
1211
( ProjectConfig(..), ProjectConfigShared(..)
1312
, commandLineFlagsToProjectConfig, writeProjectLocalFreezeConfig
1413
, findProjectRoot )
1514
import Distribution.Client.ProjectPlanning.Types
16-
( ElaboratedConfiguredPackage(..) )
1715
import Distribution.Client.Targets
1816
( UserConstraint(..) )
1917
import Distribution.Solver.Types.ConstraintSource
@@ -149,16 +147,18 @@ projectFreezeConstraints plan =
149147
flagAssignments =
150148
Map.fromList
151149
[ (pkgname, flags)
152-
| InstallPlan.Configured pkg <- InstallPlan.toList plan
153-
, let flags = pkgFlagAssignment pkg
150+
| InstallPlan.Configured pkg_or_comp <- InstallPlan.toList plan
151+
, let pkg = getElaboratedPackage pkg_or_comp
152+
flags = pkgFlagAssignment pkg
154153
pkgname = packageName pkg
155154
, not (null flags) ]
156155

157156
localPackages :: Map PackageName ()
158157
localPackages =
159158
Map.fromList
160159
[ (packageName pkg, ())
161-
| InstallPlan.Configured pkg <- InstallPlan.toList plan
160+
| InstallPlan.Configured pkg_or_comp <- InstallPlan.toList plan
161+
, let pkg = getElaboratedPackage pkg_or_comp
162162
, pkgLocalToProject pkg
163163
]
164164

cabal-install/Distribution/Client/CmdRepl.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ replAction (configFlags, configExFlags, installFlags, haddockFlags)
6767
-- repl targets (as opposed to say build or haddock targets).
6868
selectReplTargets =
6969
selectTargets
70+
verbosity
7071
ReplDefaultComponent
7172
ReplSpecificComponent
7273

cabal-install/Distribution/Client/DistDirLayout.hs

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,43 @@
55
-- The layout of the .\/dist\/ directory where cabal keeps all of it's state
66
-- and build artifacts.
77
--
8-
module Distribution.Client.DistDirLayout where
8+
module Distribution.Client.DistDirLayout (
9+
-- 'DistDirLayout'
10+
DistDirLayout(..),
11+
DistDirParams(..),
12+
defaultDistDirLayout,
13+
14+
-- * 'CabalDirLayout'
15+
CabalDirLayout(..),
16+
defaultCabalDirLayout,
17+
) where
918

1019
import System.FilePath
1120
import Distribution.Package
12-
( PackageId )
21+
( PackageId, UnitId(..) )
1322
import Distribution.Compiler
1423
import Distribution.Simple.Compiler (PackageDB(..))
1524
import Distribution.Text
25+
import Distribution.Types.ComponentName
26+
import Distribution.System
1627
import Distribution.Client.Types
1728
( InstalledPackageId )
1829

30+
-- | Information which can be used to construct the path to
31+
-- the build directory of a build. This is LESS fine-grained
32+
-- than what goes into the hashed 'InstalledPackageId',
33+
-- and for good reason: we don't want this path to change if
34+
-- the user, say, adds a dependency to their project.
35+
data DistDirParams = DistDirParams {
36+
distParamUnitId :: UnitId,
37+
distParamPackageId :: PackageId,
38+
distParamComponentName :: Maybe ComponentName,
39+
distParamCompilerId :: CompilerId,
40+
distParamPlatform :: Platform
41+
-- TODO (see #3343):
42+
-- Flag assignments
43+
-- Optimization
44+
}
1945

2046

2147
-- | The layout of the project state directory. Traditionally this has been
@@ -31,11 +57,11 @@ data DistDirLayout = DistDirLayout {
3157
-- | The directory under dist where we keep the build artifacts for a
3258
-- package we're building from a local directory.
3359
--
34-
-- This uses a 'PackageId' not just a 'PackageName' because technically
60+
-- This uses a 'UnitId' not just a 'PackageName' because technically
3561
-- we can have multiple instances of the same package in a solution
3662
-- (e.g. setup deps).
3763
--
38-
distBuildDirectory :: PackageId -> FilePath,
64+
distBuildDirectory :: DistDirParams -> FilePath,
3965
distBuildRootDirectory :: FilePath,
4066

4167
-- | The directory under dist where we put the unpacked sources of
@@ -55,8 +81,8 @@ data DistDirLayout = DistDirLayout {
5581
-- | The location for package-specific cache files (e.g. state used in
5682
-- incremental rebuilds).
5783
--
58-
distPackageCacheFile :: PackageId -> String -> FilePath,
59-
distPackageCacheDirectory :: PackageId -> FilePath,
84+
distPackageCacheFile :: DistDirParams -> String -> FilePath,
85+
distPackageCacheDirectory :: DistDirParams -> FilePath,
6086

6187
distTempDirectory :: FilePath,
6288
distBinDirectory :: FilePath,
@@ -88,7 +114,17 @@ defaultDistDirLayout projectRootDirectory =
88114
--TODO: switch to just dist at some point, or some other new name
89115

90116
distBuildRootDirectory = distDirectory </> "build"
91-
distBuildDirectory pkgid = distBuildRootDirectory </> display pkgid
117+
distBuildDirectory params =
118+
distBuildRootDirectory </>
119+
display (distParamPlatform params) </>
120+
display (distParamCompilerId params) </>
121+
display (distParamPackageId params) </>
122+
(case fmap componentNameString (distParamComponentName params) of
123+
Nothing -> ""
124+
Just Nothing -> ""
125+
Just (Just str) -> "c" </> str) </>
126+
(case distParamUnitId params of -- For Backpack
127+
SimpleUnitId _ -> "")
92128

93129
distUnpackedSrcRootDirectory = distDirectory </> "src"
94130
distUnpackedSrcDirectory pkgid = distUnpackedSrcRootDirectory
@@ -97,8 +133,8 @@ defaultDistDirLayout projectRootDirectory =
97133
distProjectCacheDirectory = distDirectory </> "cache"
98134
distProjectCacheFile name = distProjectCacheDirectory </> name
99135

100-
distPackageCacheDirectory pkgid = distBuildDirectory pkgid </> "cache"
101-
distPackageCacheFile pkgid name = distPackageCacheDirectory pkgid </> name
136+
distPackageCacheDirectory params = distBuildDirectory params </> "cache"
137+
distPackageCacheFile params name = distPackageCacheDirectory params </> name
102138

103139
distTempDirectory = distDirectory </> "tmp"
104140

cabal-install/Distribution/Client/Install.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ import Distribution.Solver.Types.ConstraintSource
116116
import Distribution.Solver.Types.LabeledPackageConstraint
117117
import Distribution.Solver.Types.OptionalStanza
118118
import qualified Distribution.Solver.Types.PackageIndex as SourcePackageIndex
119-
import Distribution.Solver.Types.PackageFixedDeps
120119
import Distribution.Solver.Types.PkgConfigDb
121120
( PkgConfigDb, readPkgConfigDb )
122121
import Distribution.Solver.Types.SourcePackage as SourcePackage
@@ -614,12 +613,12 @@ packageStatus installedPkgIndex cpkg =
614613
changes :: Installed.InstalledPackageInfo
615614
-> ReadyPackage
616615
-> [MergeResult PackageIdentifier PackageIdentifier]
617-
changes pkg pkg' = filter changed $
616+
changes pkg (ReadyPackage pkg') = filter changed $
618617
mergeBy (comparing packageName)
619618
-- deps of installed pkg
620619
(resolveInstalledIds $ Installed.depends pkg)
621620
-- deps of configured pkg
622-
(resolveInstalledIds $ CD.nonSetupDeps (depends pkg'))
621+
(resolveInstalledIds $ map confInstId (CD.nonSetupDeps (confPkgDeps pkg')))
623622

624623
-- convert to source pkg ids via index
625624
resolveInstalledIds :: [UnitId] -> [PackageIdentifier]

0 commit comments

Comments
 (0)