1 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
2 {-# LANGUAGE OverloadedStrings #-}
3 {-# LANGUAGE RecordWildCards #-}
4 {-# LANGUAGE ScopedTypeVariables #-}
6 -- | DSL for testing the modular solver
7 module UnitTests
.Distribution
.Solver
.Modular
.DSL
8 ( ExampleDependency
(..)
21 , ExampleAvailable
(..)
22 , ExampleInstalled
(..)
23 , ExampleQualifier
(..)
28 , unbuildableDependencies
51 import Distribution
.Solver
.Compat
.Prelude
52 import Distribution
.Utils
.Generic
56 import Control
.Arrow
(second
)
57 import qualified Data
.Map
as Map
58 import qualified Distribution
.Compat
.NonEmptySet
as NonEmptySet
61 import qualified Distribution
.CabalSpecVersion
as C
62 import qualified Distribution
.Compiler
as C
63 import qualified Distribution
.InstalledPackageInfo
as IPI
64 import Distribution
.License
(License
(..))
65 import qualified Distribution
.ModuleName
as Module
66 import qualified Distribution
.Package
as C
hiding
69 import qualified Distribution
.PackageDescription
as C
70 import qualified Distribution
.PackageDescription
.Check
as C
71 import qualified Distribution
.Simple
.PackageIndex
as C
.PackageIndex
72 import Distribution
.Simple
.Setup
(BooleanFlag
(..))
73 import qualified Distribution
.System
as C
74 import Distribution
.Text
(display
)
75 import qualified Distribution
.Utils
.Path
as C
76 import qualified Distribution
.Verbosity
as C
77 import qualified Distribution
.Version
as C
78 import Language
.Haskell
.Extension
(Extension
(..), Language
(..))
81 import Distribution
.Client
.Dependency
82 import qualified Distribution
.Client
.SolverInstallPlan
as CI
.SolverInstallPlan
83 import Distribution
.Client
.Types
85 import Distribution
.Solver
.Types
.ComponentDeps
(ComponentDeps
)
86 import qualified Distribution
.Solver
.Types
.ComponentDeps
as CD
87 import Distribution
.Solver
.Types
.ConstraintSource
88 import Distribution
.Solver
.Types
.Flag
89 import Distribution
.Solver
.Types
.LabeledPackageConstraint
90 import Distribution
.Solver
.Types
.OptionalStanza
91 import Distribution
.Solver
.Types
.PackageConstraint
92 import qualified Distribution
.Solver
.Types
.PackageIndex
as CI
.PackageIndex
93 import qualified Distribution
.Solver
.Types
.PackagePath
as P
94 import qualified Distribution
.Solver
.Types
.PkgConfigDb
as PC
95 import Distribution
.Solver
.Types
.Settings
96 import Distribution
.Solver
.Types
.SolverPackage
97 import Distribution
.Solver
.Types
.SourcePackage
98 import Distribution
.Solver
.Types
.Variable
100 {-------------------------------------------------------------------------------
101 Example package database DSL
103 In order to be able to set simple examples up quickly, we define a very
104 simple version of the package database here explicitly designed for use in
107 The design of `ExampleDb` takes the perspective of the solver, not the
108 perspective of the package DB. This makes it easier to set up tests for
109 various parts of the solver, but makes the mapping somewhat awkward, because
110 it means we first map from "solver perspective" `ExampleDb` to the package
111 database format, and then the modular solver internally in `IndexConversion`
112 maps this back to the solver specific data structures.
117 TODO: Perhaps these should be made comments of the corresponding data type
118 definitions. For now these are just my own conclusions and may be wrong.
120 * The difference between `GenericPackageDescription` and `PackageDescription`
121 is that `PackageDescription` describes a particular _configuration_ of a
122 package (for instance, see documentation for `checkPackage`). A
123 `GenericPackageDescription` can be turned into a `PackageDescription` in
126 a. `finalizePD` does the proper translation, by taking
127 into account the platform, available dependencies, etc. and picks a
128 flag assignment (or gives an error if no flag assignment can be found)
129 b. `flattenPackageDescription` ignores flag assignment and just joins all
132 The slightly odd thing is that a `GenericPackageDescription` contains a
133 `PackageDescription` as a field; both of the above functions do the same
134 thing: they take the embedded `PackageDescription` as a basis for the result
135 value, but override `library`, `executables`, `testSuites`, `benchmarks`
137 * The `condTreeComponents` fields of a `CondTree` is a list of triples
138 `(condition, then-branch, else-branch)`, where the `else-branch` is
140 -------------------------------------------------------------------------------}
142 type ExamplePkgName
= String
143 type ExamplePkgVersion
= Int
144 type ExamplePkgHash
= String -- for example "installed" packages
145 type ExampleFlagName
= String
146 type ExampleSubLibName
= String
147 type ExampleTestName
= String
148 type ExampleExeName
= String
149 type ExampleVersionRange
= C
.VersionRange
151 data Dependencies
= Dependencies
152 { depsVisibility
:: C
.LibraryVisibility
153 , depsIsBuildable
:: Bool
154 , depsExampleDependencies
:: [ExampleDependency
]
158 instance Semigroup Dependencies
where
161 { depsVisibility
= depsVisibility deps1
<> depsVisibility deps2
162 , depsIsBuildable
= depsIsBuildable deps1
&& depsIsBuildable deps2
163 , depsExampleDependencies
= depsExampleDependencies deps1
++ depsExampleDependencies deps2
166 instance Monoid Dependencies
where
169 { depsVisibility
= mempty
170 , depsIsBuildable
= True
171 , depsExampleDependencies
= []
175 dependencies
:: [ExampleDependency
] -> Dependencies
176 dependencies deps
= mempty
{depsExampleDependencies
= deps
}
178 publicDependencies
:: Dependencies
179 publicDependencies
= mempty
{depsVisibility
= C
.LibraryVisibilityPublic
}
181 unbuildableDependencies
:: Dependencies
182 unbuildableDependencies
= mempty
{depsIsBuildable
= False}
184 data ExampleDependency
185 = -- | Simple dependency on any version
187 |
-- | Simple dependency on a fixed version
188 ExFix ExamplePkgName ExamplePkgVersion
189 |
-- | Simple dependency on a range of versions, with an inclusive lower bound
190 -- and an exclusive upper bound.
191 ExRange ExamplePkgName ExamplePkgVersion ExamplePkgVersion
192 |
-- | Sub-library dependency
193 ExSubLibAny ExamplePkgName ExampleSubLibName
194 |
-- | Sub-library dependency on a fixed version
195 ExSubLibFix ExamplePkgName ExampleSubLibName ExamplePkgVersion
196 |
-- | Build-tool-depends dependency
197 ExBuildToolAny ExamplePkgName ExampleExeName
198 |
-- | Build-tool-depends dependency on a fixed version
199 ExBuildToolFix ExamplePkgName ExampleExeName ExamplePkgVersion
200 |
-- | Legacy build-tools dependency
201 ExLegacyBuildToolAny ExamplePkgName
202 |
-- | Legacy build-tools dependency on a fixed version
203 ExLegacyBuildToolFix ExamplePkgName ExamplePkgVersion
204 |
-- | Dependencies indexed by a flag
205 ExFlagged ExampleFlagName Dependencies Dependencies
206 |
-- | Dependency on a language extension
208 |
-- | Dependency on a language version
210 |
-- | Dependency on a pkg-config package
211 ExPkg
(ExamplePkgName
, ExamplePkgVersion
)
214 -- | Simplified version of D.Types.GenericPackageDescription.Flag for use in
215 -- example source packages.
217 { exFlagName
:: ExampleFlagName
218 , exFlagDefault
:: Bool
219 , exFlagType
:: FlagType
223 data ExSubLib
= ExSubLib ExampleSubLibName Dependencies
225 data ExTest
= ExTest ExampleTestName Dependencies
227 data ExExe
= ExExe ExampleExeName Dependencies
229 exSubLib
:: ExampleSubLibName
-> [ExampleDependency
] -> ExSubLib
230 exSubLib name deps
= ExSubLib name
(dependencies deps
)
232 exTest
:: ExampleTestName
-> [ExampleDependency
] -> ExTest
233 exTest name deps
= ExTest name
(dependencies deps
)
235 exExe
:: ExampleExeName
-> [ExampleDependency
] -> ExExe
236 exExe name deps
= ExExe name
(dependencies deps
)
240 -> [ExampleDependency
]
241 -> [ExampleDependency
]
243 exFlagged n t e
= ExFlagged n
(dependencies t
) (dependencies e
)
246 = ExVersionConstraint ConstraintScope ExampleVersionRange
247 | ExFlagConstraint ConstraintScope ExampleFlagName
Bool
248 | ExStanzaConstraint ConstraintScope
[OptionalStanza
]
252 = ExPkgPref ExamplePkgName ExampleVersionRange
253 | ExStanzaPref ExamplePkgName
[OptionalStanza
]
256 data ExampleAvailable
= ExAv
257 { exAvName
:: ExamplePkgName
258 , exAvVersion
:: ExamplePkgVersion
259 , exAvDeps
:: ComponentDeps Dependencies
260 , -- Setting flags here is only necessary to override the default values of
261 -- the fields in C.Flag.
262 exAvFlags
:: [ExFlag
]
267 = P ExampleQualifier ExamplePkgName
268 | F ExampleQualifier ExamplePkgName ExampleFlagName
269 | S ExampleQualifier ExamplePkgName OptionalStanza
271 data ExampleQualifier
273 | QualIndep ExamplePkgName
274 | QualSetup ExamplePkgName
275 |
-- The two package names are the build target and the package containing the
277 QualIndepSetup ExamplePkgName ExamplePkgName
278 |
-- The two package names are the package depending on the exe and the
279 -- package containing the exe.
280 QualExe ExamplePkgName ExamplePkgName
282 -- | Whether to enable tests in all packages in a test case.
283 newtype EnableAllTests
= EnableAllTests
Bool
284 deriving (BooleanFlag
)
286 -- | Constructs an 'ExampleAvailable' package for the 'ExampleDb',
289 -- 1. The name 'ExamplePkgName' of the available package,
290 -- 2. The version 'ExamplePkgVersion' available
291 -- 3. The list of dependency constraints ('ExampleDependency')
292 -- for this package's library component. 'ExampleDependency'
293 -- provides a number of pre-canned dependency types to look at.
297 -> [ExampleDependency
]
299 exAv n v ds
= (exAvNoLibrary n v
){exAvDeps
= CD
.fromLibraryDeps
(dependencies ds
)}
301 -- | Constructs an 'ExampleAvailable' package without a default library
303 exAvNoLibrary
:: ExamplePkgName
-> ExamplePkgVersion
-> ExampleAvailable
308 , exAvDeps
= CD
.empty
312 -- | Override the default settings (e.g., manual vs. automatic) for a subset of
313 -- a package's flags.
314 declareFlags
:: [ExFlag
] -> ExampleAvailable
-> ExampleAvailable
315 declareFlags flags ex
=
320 withSubLibrary
:: ExampleAvailable
-> ExSubLib
-> ExampleAvailable
321 withSubLibrary ex lib
= withSubLibraries ex
[lib
]
323 withSubLibraries
:: ExampleAvailable
-> [ExSubLib
] -> ExampleAvailable
324 withSubLibraries ex libs
=
327 [ (CD
.ComponentSubLib
$ C
.mkUnqualComponentName name
, deps
)
328 | ExSubLib name deps
<- libs
330 in ex
{exAvDeps
= exAvDeps ex
<> subLibCDs
}
332 withSetupDeps
:: ExampleAvailable
-> [ExampleDependency
] -> ExampleAvailable
333 withSetupDeps ex setupDeps
=
335 { exAvDeps
= exAvDeps ex
<> CD
.fromSetupDeps
(dependencies setupDeps
)
338 withTest
:: ExampleAvailable
-> ExTest
-> ExampleAvailable
339 withTest ex test
= withTests ex
[test
]
341 withTests
:: ExampleAvailable
-> [ExTest
] -> ExampleAvailable
345 [ (CD
.ComponentTest
$ C
.mkUnqualComponentName name
, deps
)
346 | ExTest name deps
<- tests
348 in ex
{exAvDeps
= exAvDeps ex
<> testCDs
}
350 withExe
:: ExampleAvailable
-> ExExe
-> ExampleAvailable
351 withExe ex exe
= withExes ex
[exe
]
353 withExes
:: ExampleAvailable
-> [ExExe
] -> ExampleAvailable
357 [ (CD
.ComponentExe
$ C
.mkUnqualComponentName name
, deps
)
358 | ExExe name deps
<- exes
360 in ex
{exAvDeps
= exAvDeps ex
<> exeCDs
}
362 -- | An installed package in 'ExampleDb'; construct me with 'exInst'.
363 data ExampleInstalled
= ExInst
364 { exInstName
:: ExamplePkgName
365 , exInstVersion
:: ExamplePkgVersion
366 , exInstHash
:: ExamplePkgHash
367 , exInstBuildAgainst
:: [ExamplePkgHash
]
371 -- | Constructs an example installed package given:
373 -- 1. The name of the package 'ExamplePkgName', i.e., 'String'
374 -- 2. The version of the package 'ExamplePkgVersion', i.e., 'Int'
375 -- 3. The IPID for the package 'ExamplePkgHash', i.e., 'String'
376 -- (just some unique identifier for the package.)
377 -- 4. The 'ExampleInstalled' packages which this package was
378 -- compiled against.)
383 -> [ExampleInstalled
]
385 exInst pn v hash deps
= ExInst pn v hash
(map exInstHash deps
)
387 -- | An example package database is a list of installed packages
388 -- 'ExampleInstalled' and available packages 'ExampleAvailable'.
389 -- Generally, you want to use 'exInst' and 'exAv' to construct
391 type ExampleDb
= [Either ExampleInstalled ExampleAvailable
]
393 type DependencyTree a
= C
.CondTree C
.ConfVar
[C
.Dependency
] a
395 type DependencyComponent a
= C
.CondBranch C
.ConfVar
[C
.Dependency
] a
397 exDbPkgs
:: ExampleDb
-> [ExamplePkgName
]
398 exDbPkgs
= map (either exInstName exAvName
)
400 exAvSrcPkg
:: ExampleAvailable
-> UnresolvedSourcePackage
402 let pkgId
= exAvPkgId ex
404 flags
:: [C
.PackageFlag
]
406 let declaredFlags
:: Map ExampleFlagName C
.PackageFlag
409 (\f1 f2
-> error $ "duplicate flag declarations: " ++ show [f1
, f2
])
410 [(exFlagName flag
, mkFlag flag
) | flag
<- exAvFlags ex
]
412 usedFlags
:: Map ExampleFlagName C
.PackageFlag
413 usedFlags
= Map
.fromList
[(fn
, mkDefaultFlag fn
) | fn
<- names
]
415 names
= extractFlags
$ CD
.flatDeps
(exAvDeps ex
)
416 in -- 'declaredFlags' overrides 'usedFlags' to give flags non-default settings:
417 Map
.elems $ declaredFlags `Map
.union` usedFlags
419 subLibraries
= [(name
, deps
) |
(CD
.ComponentSubLib name
, deps
) <- CD
.toList
(exAvDeps ex
)]
420 foreignLibraries
= [(name
, deps
) |
(CD
.ComponentFLib name
, deps
) <- CD
.toList
(exAvDeps ex
)]
421 testSuites
= [(name
, deps
) |
(CD
.ComponentTest name
, deps
) <- CD
.toList
(exAvDeps ex
)]
422 benchmarks
= [(name
, deps
) |
(CD
.ComponentBench name
, deps
) <- CD
.toList
(exAvDeps ex
)]
423 executables
= [(name
, deps
) |
(CD
.ComponentExe name
, deps
) <- CD
.toList
(exAvDeps ex
)]
424 setup
= case depsExampleDependencies
$ CD
.setupDeps
(exAvDeps ex
) of
429 { C
.setupDepends
= mkSetupDeps deps
430 , C
.defaultSetupDepends
= False
434 { srcpkgPackageId
= pkgId
435 , srcpkgSource
= LocalTarballPackage
"<<path>>"
436 , srcpkgDescrOverride
= Nothing
437 , srcpkgDescription
=
438 C
.GenericPackageDescription
439 { C
.packageDescription
=
440 C
.emptyPackageDescription
442 , C
.setupBuildInfo
= setup
443 , C
.licenseRaw
= Right BSD3
448 , C
.category
= "category"
449 , C
.maintainer
= "maintainer"
450 , C
.description
= "description"
451 , C
.synopsis
= "synopsis"
452 , C
.licenseFiles
= [C
.makeRelativePathEx
"LICENSE"]
453 , -- Version 2.0 is required for internal libraries.
454 C
.specVersion
= C
.CabalSpecV2_0
456 , C
.gpdScannedVersion
= Nothing
457 , C
.genPackageFlags
= flags
459 let mkLib v bi
= mempty
{C
.libVisibility
= v
, C
.libBuildInfo
= bi
}
460 -- Avoid using the Monoid instance for [a] when getting
461 -- the library dependencies, to allow for the possibility
462 -- that the package doesn't have a library:
463 libDeps
= lookup CD
.ComponentLib
(CD
.toList
(exAvDeps ex
))
464 in mkTopLevelCondTree defaultLib mkLib
<$> libDeps
465 , C
.condSubLibraries
=
466 let mkTree
= mkTopLevelCondTree defaultSubLib mkLib
467 mkLib v bi
= mempty
{C
.libVisibility
= v
, C
.libBuildInfo
= bi
}
468 in map (second mkTree
) subLibraries
469 , C
.condForeignLibs
=
470 let mkTree
= mkTopLevelCondTree
(mkLib defaultTopLevelBuildInfo
) (const mkLib
)
471 mkLib bi
= mempty
{C
.foreignLibBuildInfo
= bi
}
472 in map (second mkTree
) foreignLibraries
473 , C
.condExecutables
=
474 let mkTree
= mkTopLevelCondTree defaultExe
(const mkExe
)
475 mkExe bi
= mempty
{C
.buildInfo
= bi
}
476 in map (second mkTree
) executables
478 let mkTree
= mkTopLevelCondTree defaultTest
(const mkTest
)
479 mkTest bi
= mempty
{C
.testBuildInfo
= bi
}
480 in map (second mkTree
) testSuites
482 let mkTree
= mkTopLevelCondTree defaultBenchmark
(const mkBench
)
483 mkBench bi
= mempty
{C
.benchmarkBuildInfo
= bi
}
484 in map (second mkTree
) benchmarks
488 -- We ignore unknown extensions/languages warnings because
489 -- some there are some unit tests test in which the solver allows
490 -- unknown extensions/languages when the compiler supports them.
491 -- Furthermore we ignore missing upper bound warnings because
492 -- they are not related to this test suite, and are tested
493 -- with golden tests.
494 let checks
= C
.checkPackage
(srcpkgDescription package
)
495 in filter (\x
-> not (isMissingUpperBound x
) && not (isUnknownLangExt x
)) checks
496 in if null pkgCheckErrors
500 "invalid GenericPackageDescription for package "
503 ++ show pkgCheckErrors
505 defaultTopLevelBuildInfo
:: C
.BuildInfo
506 defaultTopLevelBuildInfo
= mempty
{C
.defaultLanguage
= Just Haskell98
}
508 defaultLib
:: C
.Library
511 { C
.libBuildInfo
= defaultTopLevelBuildInfo
512 , C
.exposedModules
= [Module
.fromString
"Module"]
513 , C
.libVisibility
= C
.LibraryVisibilityPublic
516 defaultSubLib
:: C
.Library
519 { C
.libBuildInfo
= defaultTopLevelBuildInfo
520 , C
.exposedModules
= [Module
.fromString
"Module"]
523 defaultExe
:: C
.Executable
526 { C
.buildInfo
= defaultTopLevelBuildInfo
527 , C
.modulePath
= C
.makeRelativePathEx
"Main.hs"
530 defaultTest
:: C
.TestSuite
533 { C
.testBuildInfo
= defaultTopLevelBuildInfo
535 C
.TestSuiteExeV10
(C
.mkVersion
[1, 0]) $
536 C
.makeRelativePathEx
"Test.hs"
539 defaultBenchmark
:: C
.Benchmark
542 { C
.benchmarkBuildInfo
= defaultTopLevelBuildInfo
543 , C
.benchmarkInterface
=
544 C
.BenchmarkExeV10
(C
.mkVersion
[1, 0]) $
545 C
.makeRelativePathEx
"Benchmark.hs"
548 -- Split the set of dependencies into the set of dependencies of the library,
549 -- the dependencies of the test suites and extensions.
551 :: [ExampleDependency
]
552 -> ( [ExampleDependency
]
555 , [(ExamplePkgName
, ExamplePkgVersion
)] -- pkg-config
556 , [(ExamplePkgName
, ExampleExeName
, C
.VersionRange
)] -- build tools
557 , [(ExamplePkgName
, C
.VersionRange
)] -- legacy build tools
560 ([], [], Nothing
, [], [], [])
561 splitTopLevel
(ExBuildToolAny p e
: deps
) =
562 let (other
, exts
, lang
, pcpkgs
, exes
, legacyExes
) = splitTopLevel deps
563 in (other
, exts
, lang
, pcpkgs
, (p
, e
, C
.anyVersion
) : exes
, legacyExes
)
564 splitTopLevel
(ExBuildToolFix p e v
: deps
) =
565 let (other
, exts
, lang
, pcpkgs
, exes
, legacyExes
) = splitTopLevel deps
566 in (other
, exts
, lang
, pcpkgs
, (p
, e
, C
.thisVersion
(mkSimpleVersion v
)) : exes
, legacyExes
)
567 splitTopLevel
(ExLegacyBuildToolAny p
: deps
) =
568 let (other
, exts
, lang
, pcpkgs
, exes
, legacyExes
) = splitTopLevel deps
569 in (other
, exts
, lang
, pcpkgs
, exes
, (p
, C
.anyVersion
) : legacyExes
)
570 splitTopLevel
(ExLegacyBuildToolFix p v
: deps
) =
571 let (other
, exts
, lang
, pcpkgs
, exes
, legacyExes
) = splitTopLevel deps
572 in (other
, exts
, lang
, pcpkgs
, exes
, (p
, C
.thisVersion
(mkSimpleVersion v
)) : legacyExes
)
573 splitTopLevel
(ExExt ext
: deps
) =
574 let (other
, exts
, lang
, pcpkgs
, exes
, legacyExes
) = splitTopLevel deps
575 in (other
, ext
: exts
, lang
, pcpkgs
, exes
, legacyExes
)
576 splitTopLevel
(ExLang lang
: deps
) =
577 case splitTopLevel deps
of
578 (other
, exts
, Nothing
, pcpkgs
, exes
, legacyExes
) -> (other
, exts
, Just lang
, pcpkgs
, exes
, legacyExes
)
579 _
-> error "Only 1 Language dependency is supported"
580 splitTopLevel
(ExPkg pkg
: deps
) =
581 let (other
, exts
, lang
, pcpkgs
, exes
, legacyExes
) = splitTopLevel deps
582 in (other
, exts
, lang
, pkg
: pcpkgs
, exes
, legacyExes
)
583 splitTopLevel
(dep
: deps
) =
584 let (other
, exts
, lang
, pcpkgs
, exes
, legacyExes
) = splitTopLevel deps
585 in (dep
: other
, exts
, lang
, pcpkgs
, exes
, legacyExes
)
587 -- Extract the total set of flags used
588 extractFlags
:: Dependencies
-> [ExampleFlagName
]
589 extractFlags deps
= concatMap go
(depsExampleDependencies deps
)
591 go
:: ExampleDependency
-> [ExampleFlagName
]
594 go
(ExRange _ _ _
) = []
595 go
(ExSubLibAny _ _
) = []
596 go
(ExSubLibFix _ _ _
) = []
597 go
(ExBuildToolAny _ _
) = []
598 go
(ExBuildToolFix _ _ _
) = []
599 go
(ExLegacyBuildToolAny _
) = []
600 go
(ExLegacyBuildToolFix _ _
) = []
601 go
(ExFlagged f a b
) = f
: extractFlags a
++ extractFlags b
606 -- Convert 'Dependencies' into a tree of a specific component type, using
607 -- the given top level component and function for creating a component at
613 -> (C
.LibraryVisibility
-> C
.BuildInfo
-> a
)
616 mkTopLevelCondTree defaultTopLevel mkComponent deps
=
617 let condNode
= mkCondTree mkComponent deps
618 in condNode
{C
.condTreeData
= defaultTopLevel
<> C
.condTreeData condNode
}
620 -- Convert 'Dependencies' into a tree of a specific component type, using
621 -- the given function to generate each component.
622 mkCondTree
:: (C
.LibraryVisibility
-> C
.BuildInfo
-> a
) -> Dependencies
-> DependencyTree a
623 mkCondTree mkComponent deps
=
624 let (libraryDeps
, exts
, mlang
, pcpkgs
, buildTools
, legacyBuildTools
) = splitTopLevel
(depsExampleDependencies deps
)
625 (directDeps
, flaggedDeps
) = splitDeps libraryDeps
626 component
= mkComponent
(depsVisibility deps
) bi
629 { C
.otherExtensions
= exts
630 , C
.defaultLanguage
= mlang
631 , C
.buildToolDepends
=
632 [ C
.ExeDependency
(C
.mkPackageName p
) (C
.mkUnqualComponentName e
) vr
633 |
(p
, e
, vr
) <- buildTools
636 [ C
.LegacyExeDependency n vr
637 |
(n
, vr
) <- legacyBuildTools
639 , C
.pkgconfigDepends
=
640 [ C
.PkgconfigDependency n
' v
'
642 , let n
' = C
.mkPkgconfigName n
643 , let v
' = C
.PcThisVersion
(mkSimplePkgconfigVersion v
)
645 , C
.buildable
= depsIsBuildable deps
648 { C
.condTreeData
= component
649 , -- TODO: Arguably, build-tools dependencies should also
650 -- effect constraints on conditional tree. But no way to
651 -- distinguish between them
652 C
.condTreeConstraints
= map mkDirect directDeps
653 , C
.condTreeComponents
= map (mkFlagged mkComponent
) flaggedDeps
656 mkDirect
:: (ExamplePkgName
, C
.LibraryName
, C
.VersionRange
) -> C
.Dependency
657 mkDirect
(dep
, name
, vr
) = C
.Dependency
(C
.mkPackageName dep
) vr
(NonEmptySet
.singleton name
)
660 :: (C
.LibraryVisibility
-> C
.BuildInfo
-> a
)
661 -> (ExampleFlagName
, Dependencies
, Dependencies
)
662 -> DependencyComponent a
663 mkFlagged mkComponent
(f
, a
, b
) =
665 (C
.Var
(C
.PackageFlag
(C
.mkFlagName f
)))
666 (mkCondTree mkComponent a
)
667 (Just
(mkCondTree mkComponent b
))
669 -- Split a set of dependencies into direct dependencies and flagged
670 -- dependencies. A direct dependency is a tuple of the name of package and
671 -- its version range meant to be converted to a 'C.Dependency' with
672 -- 'mkDirect' for example. A flagged dependency is the set of dependencies
673 -- guarded by a flag.
675 :: [ExampleDependency
]
676 -> ( [(ExamplePkgName
, C
.LibraryName
, C
.VersionRange
)]
677 , [(ExampleFlagName
, Dependencies
, Dependencies
)]
681 splitDeps
(ExAny p
: deps
) =
682 let (directDeps
, flaggedDeps
) = splitDeps deps
683 in ((p
, C
.LMainLibName
, C
.anyVersion
) : directDeps
, flaggedDeps
)
684 splitDeps
(ExFix p v
: deps
) =
685 let (directDeps
, flaggedDeps
) = splitDeps deps
686 in ((p
, C
.LMainLibName
, C
.thisVersion
$ mkSimpleVersion v
) : directDeps
, flaggedDeps
)
687 splitDeps
(ExRange p v1 v2
: deps
) =
688 let (directDeps
, flaggedDeps
) = splitDeps deps
689 in ((p
, C
.LMainLibName
, mkVersionRange v1 v2
) : directDeps
, flaggedDeps
)
690 splitDeps
(ExSubLibAny p lib
: deps
) =
691 let (directDeps
, flaggedDeps
) = splitDeps deps
692 in ((p
, C
.LSubLibName
(C
.mkUnqualComponentName lib
), C
.anyVersion
) : directDeps
, flaggedDeps
)
693 splitDeps
(ExSubLibFix p lib v
: deps
) =
694 let (directDeps
, flaggedDeps
) = splitDeps deps
695 in ((p
, C
.LSubLibName
(C
.mkUnqualComponentName lib
), C
.thisVersion
$ mkSimpleVersion v
) : directDeps
, flaggedDeps
)
696 splitDeps
(ExFlagged f a b
: deps
) =
697 let (directDeps
, flaggedDeps
) = splitDeps deps
698 in (directDeps
, (f
, a
, b
) : flaggedDeps
)
699 splitDeps
(dep
: _
) = error $ "Unexpected dependency: " ++ show dep
701 -- custom-setup only supports simple dependencies
702 mkSetupDeps
:: [ExampleDependency
] -> [C
.Dependency
]
704 case splitDeps deps
of
705 (directDeps
, []) -> map mkDirect directDeps
706 _
-> error "mkSetupDeps: custom setup has non-simple deps"
708 -- Check for `UnknownLanguages` and `UnknownExtensions`. See
709 isUnknownLangExt
:: C
.PackageCheck
-> Bool
710 isUnknownLangExt pc
= case C
.explanation pc
of
711 C
.UnknownExtensions
{} -> True
712 C
.UnknownLanguages
{} -> True
714 isMissingUpperBound
:: C
.PackageCheck
-> Bool
715 isMissingUpperBound pc
= case C
.explanation pc
of
716 C
.MissingUpperBounds
{} -> True
719 mkSimpleVersion
:: ExamplePkgVersion
-> C
.Version
720 mkSimpleVersion n
= C
.mkVersion
[n
, 0, 0]
722 mkSimplePkgconfigVersion
:: ExamplePkgVersion
-> C
.PkgconfigVersion
723 mkSimplePkgconfigVersion
= C
.versionToPkgconfigVersion
. mkSimpleVersion
725 mkVersionRange
:: ExamplePkgVersion
-> ExamplePkgVersion
-> C
.VersionRange
726 mkVersionRange v1 v2
=
727 C
.intersectVersionRanges
728 (C
.orLaterVersion
$ mkSimpleVersion v1
)
729 (C
.earlierVersion
$ mkSimpleVersion v2
)
731 mkFlag
:: ExFlag
-> C
.PackageFlag
734 { C
.flagName
= C
.mkFlagName
$ exFlagName flag
735 , C
.flagDescription
= ""
736 , C
.flagDefault
= exFlagDefault flag
738 case exFlagType flag
of
743 mkDefaultFlag
:: ExampleFlagName
-> C
.PackageFlag
746 { C
.flagName
= C
.mkFlagName flag
747 , C
.flagDescription
= ""
748 , C
.flagDefault
= True
749 , C
.flagManual
= False
752 exAvPkgId
:: ExampleAvailable
-> C
.PackageIdentifier
755 { pkgName
= C
.mkPackageName
(exAvName ex
)
756 , pkgVersion
= C
.mkVersion
[exAvVersion ex
, 0, 0]
759 exInstInfo
:: ExampleInstalled
-> IPI
.InstalledPackageInfo
761 IPI
.emptyInstalledPackageInfo
762 { IPI
.installedUnitId
= C
.mkUnitId
(exInstHash ex
)
763 , IPI
.sourcePackageId
= exInstPkgId ex
764 , IPI
.depends
= map C
.mkUnitId
(exInstBuildAgainst ex
)
767 exInstPkgId
:: ExampleInstalled
-> C
.PackageIdentifier
770 { pkgName
= C
.mkPackageName
(exInstName ex
)
771 , pkgVersion
= C
.mkVersion
[exInstVersion ex
, 0, 0]
774 exAvIdx
:: [ExampleAvailable
] -> CI
.PackageIndex
.PackageIndex UnresolvedSourcePackage
775 exAvIdx
= CI
.PackageIndex
.fromList
. map exAvSrcPkg
777 exInstIdx
:: [ExampleInstalled
] -> C
.PackageIndex
.InstalledPackageIndex
778 exInstIdx
= C
.PackageIndex
.fromList
. map exInstInfo
782 -- List of extensions supported by the compiler, or Nothing if unknown.
784 -- List of languages supported by the compiler, or Nothing if unknown.
786 -> Maybe PC
.PkgConfigDb
790 -> FineGrainedConflicts
791 -> MinimizeConflictSet
795 -> AllowBootLibInstalls
799 -> Maybe (Variable P
.QPN
-> Variable P
.QPN
-> Ordering)
804 -> Progress
String String CI
.SolverInstallPlan
.SolverInstallPlan
827 resolveDependencies C
.buildPlatform compiler pkgConfigDb params
829 defaultCompiler
= C
.unknownCompilerInfo C
.buildCompilerId C
.NoAbiTag
832 { C
.compilerInfoExtensions
= exts
833 , C
.compilerInfoLanguages
= langs
835 (inst
, avai
) = partitionEithers db
836 instIdx
= exInstIdx inst
839 { packageIndex
= exAvIdx avai
840 , packagePreferences
= Map
.empty
843 | asBool enableAllTests
=
847 (scopeToplevel
(C
.mkPackageName p
))
848 (PackagePropertyStanzas
[TestStanzas
])
852 targets
' = fmap (\p
-> NamedPackage
(C
.mkPackageName p
) []) targets
854 addConstraints
(fmap toConstraint constraints
) $
855 addConstraints
(fmap toLpc enableTests
) $
856 addPreferences
(fmap toPref prefs
) $
857 setCountConflicts countConflicts
$
858 setFineGrainedConflicts fineGrainedConflicts
$
859 setMinimizeConflictSet minimizeConflictSet
$
860 setIndependentGoals indepGoals
$
861 (if asBool prefOldest
then setPreferenceDefault PreferAllOldest
else id) $
862 setReorderGoals reorder
$
863 setMaxBackjumps mbj
$
864 setAllowBootLibInstalls allowBootLibInstalls
$
865 setOnlyConstrained onlyConstrained
$
866 setEnableBackjumping enableBj
$
867 setSolveExecutables solveExes
$
868 setGoalOrder goalOrder
$
869 setSolverVerbosity verbosity
$
870 standardInstallPolicy instIdx avaiIdx targets
'
871 toLpc pc
= LabeledPackageConstraint pc ConstraintSourceUnknown
873 toConstraint
(ExVersionConstraint scope v
) =
874 toLpc
$ PackageConstraint scope
(PackagePropertyVersion v
)
875 toConstraint
(ExFlagConstraint scope fn b
) =
876 toLpc
$ PackageConstraint scope
(PackagePropertyFlags
(C
.mkFlagAssignment
[(C
.mkFlagName fn
, b
)]))
877 toConstraint
(ExStanzaConstraint scope stanzas
) =
878 toLpc
$ PackageConstraint scope
(PackagePropertyStanzas stanzas
)
880 toPref
(ExPkgPref n v
) = PackageVersionPreference
(C
.mkPackageName n
) v
881 toPref
(ExStanzaPref n stanzas
) = PackageStanzasPreference
(C
.mkPackageName n
) stanzas
884 :: CI
.SolverInstallPlan
.SolverInstallPlan
885 -> [(ExamplePkgName
, ExamplePkgVersion
)]
886 extractInstallPlan
= catMaybes . map confPkg
. CI
.SolverInstallPlan
.toList
888 confPkg
:: CI
.SolverInstallPlan
.SolverPlanPackage
-> Maybe (String, Int)
889 confPkg
(CI
.SolverInstallPlan
.Configured pkg
) = srcPkg pkg
892 srcPkg
:: SolverPackage UnresolvedPkgLoc
-> Maybe (String, Int)
894 let C
.PackageIdentifier pn ver
= C
.packageId
(solverPkgSource cpkg
)
895 in (\vn
-> (C
.unPackageName pn
, vn
)) <$> safeHead
(C
.versionNumbers ver
)
897 {-------------------------------------------------------------------------------
899 -------------------------------------------------------------------------------}
901 -- | Run Progress computation
902 runProgress
:: Progress step e a
-> ([step
], Either e a
)
905 go
(Step s p
) = let (ss
, result
) = go p
in (s
: ss
, result
)
906 go
(Fail e
) = ([], Left e
)
907 go
(Done a
) = ([], Right a
)