Cabal 1.22.8.0 → 1.24.0.0
raw patch · 225 files changed
+9660/−6555 lines, 225 filesdep +Win32dep +exceptionsdep +taggeddep −HUnitdep −extensible-exceptionsdep −test-frameworkdep ~QuickCheckdep ~basedep ~bytestringsetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies added: Win32, exceptions, tagged, tasty, tasty-hunit, tasty-quickcheck, transformers
Dependencies removed: HUnit, extensible-exceptions, test-framework, test-framework-hunit, test-framework-quickcheck2
Dependency ranges changed: QuickCheck, base, bytestring, containers, directory, filepath, pretty, process, time, unix
API changes (from Hackage documentation)
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_0AbiTag
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_0CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_0CompilerId
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_0CompilerInfo
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_10CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_11CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_1AbiTag
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_1CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_2CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_3CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_4CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_5CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_6CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_7CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_8CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Constructor Distribution.Compiler.C1_9CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Datatype Distribution.Compiler.D1AbiTag
- Distribution.Compiler: instance GHC.Generics.Datatype Distribution.Compiler.D1CompilerFlavor
- Distribution.Compiler: instance GHC.Generics.Datatype Distribution.Compiler.D1CompilerId
- Distribution.Compiler: instance GHC.Generics.Datatype Distribution.Compiler.D1CompilerInfo
- Distribution.Compiler: instance GHC.Generics.Selector Distribution.Compiler.S1_0_0CompilerInfo
- Distribution.Compiler: instance GHC.Generics.Selector Distribution.Compiler.S1_0_1CompilerInfo
- Distribution.Compiler: instance GHC.Generics.Selector Distribution.Compiler.S1_0_2CompilerInfo
- Distribution.Compiler: instance GHC.Generics.Selector Distribution.Compiler.S1_0_3CompilerInfo
- Distribution.Compiler: instance GHC.Generics.Selector Distribution.Compiler.S1_0_4CompilerInfo
- Distribution.InstalledPackageInfo: [exposedSignature] :: ExposedModule -> Maybe OriginalModule
- Distribution.InstalledPackageInfo: [installedPackageId] :: InstalledPackageInfo_ m -> InstalledPackageId
- Distribution.InstalledPackageInfo: [instantiatedWith] :: InstalledPackageInfo_ m -> [(m, OriginalModule)]
- Distribution.InstalledPackageInfo: [packageKey] :: InstalledPackageInfo_ m -> PackageKey
- Distribution.InstalledPackageInfo: data InstalledPackageInfo_ m
- Distribution.InstalledPackageInfo: instance Data.Binary.Class.Binary m => Data.Binary.Class.Binary (Distribution.InstalledPackageInfo.InstalledPackageInfo_ m)
- Distribution.InstalledPackageInfo: instance Distribution.Package.Package (Distribution.InstalledPackageInfo.InstalledPackageInfo_ str)
- Distribution.InstalledPackageInfo: instance Distribution.Package.PackageInstalled (Distribution.InstalledPackageInfo.InstalledPackageInfo_ str)
- Distribution.InstalledPackageInfo: instance GHC.Generics.Constructor Distribution.InstalledPackageInfo.C1_0ExposedModule
- Distribution.InstalledPackageInfo: instance GHC.Generics.Constructor Distribution.InstalledPackageInfo.C1_0InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Constructor Distribution.InstalledPackageInfo.C1_0OriginalModule
- Distribution.InstalledPackageInfo: instance GHC.Generics.Datatype Distribution.InstalledPackageInfo.D1ExposedModule
- Distribution.InstalledPackageInfo: instance GHC.Generics.Datatype Distribution.InstalledPackageInfo.D1InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Datatype Distribution.InstalledPackageInfo.D1OriginalModule
- Distribution.InstalledPackageInfo: instance GHC.Generics.Generic (Distribution.InstalledPackageInfo.InstalledPackageInfo_ m)
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_0ExposedModule
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_0InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_0OriginalModule
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_10InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_11InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_12InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_13InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_14InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_15InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_16InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_17InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_18InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_19InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_1ExposedModule
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_1InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_1OriginalModule
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_20InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_21InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_22InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_23InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_24InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_25InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_26InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_27InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_28InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_29InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_2ExposedModule
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_2InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_30InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_31InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_32InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_33InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_3InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_4InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_5InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_6InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_7InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_8InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Generics.Selector Distribution.InstalledPackageInfo.S1_0_9InstalledPackageInfo_
- Distribution.InstalledPackageInfo: instance GHC.Read.Read m => GHC.Read.Read (Distribution.InstalledPackageInfo.InstalledPackageInfo_ m)
- Distribution.InstalledPackageInfo: instance GHC.Show.Show m => GHC.Show.Show (Distribution.InstalledPackageInfo.InstalledPackageInfo_ m)
- Distribution.InstalledPackageInfo: type InstalledPackageInfo = InstalledPackageInfo_ ModuleName
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_0License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_10License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_11License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_12License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_13License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_14License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_1License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_2License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_3License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_4License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_5License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_6License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_7License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_8License
- Distribution.License: instance GHC.Generics.Constructor Distribution.License.C1_9License
- Distribution.License: instance GHC.Generics.Datatype Distribution.License.D1License
- Distribution.ModuleName: instance GHC.Generics.Constructor Distribution.ModuleName.C1_0ModuleName
- Distribution.ModuleName: instance GHC.Generics.Datatype Distribution.ModuleName.D1ModuleName
- Distribution.Package: InstalledPackageId :: String -> InstalledPackageId
- Distribution.Package: OldPackageKey :: !PackageId -> PackageKey
- Distribution.Package: PackageKey :: !String -> {-# UNPACK #-} !Word64 -> {-# UNPACK #-} !Word64 -> PackageKey
- Distribution.Package: class Package pkg => PackageFixedDeps pkg
- Distribution.Package: data PackageKey
- Distribution.Package: depends :: PackageFixedDeps pkg => pkg -> [PackageIdentifier]
- Distribution.Package: instance Control.DeepSeq.NFData Distribution.Package.PackageKey
- Distribution.Package: instance Data.Binary.Class.Binary Distribution.Package.InstalledPackageId
- Distribution.Package: instance Data.Binary.Class.Binary Distribution.Package.PackageKey
- Distribution.Package: instance Data.Data.Data Distribution.Package.InstalledPackageId
- Distribution.Package: instance Data.Data.Data Distribution.Package.PackageKey
- Distribution.Package: instance Distribution.Text.Text Distribution.Package.InstalledPackageId
- Distribution.Package: instance Distribution.Text.Text Distribution.Package.PackageKey
- Distribution.Package: instance GHC.Classes.Eq Distribution.Package.InstalledPackageId
- Distribution.Package: instance GHC.Classes.Eq Distribution.Package.PackageKey
- Distribution.Package: instance GHC.Classes.Ord Distribution.Package.InstalledPackageId
- Distribution.Package: instance GHC.Classes.Ord Distribution.Package.PackageKey
- Distribution.Package: instance GHC.Generics.Constructor Distribution.Package.C1_0Dependency
- Distribution.Package: instance GHC.Generics.Constructor Distribution.Package.C1_0InstalledPackageId
- Distribution.Package: instance GHC.Generics.Constructor Distribution.Package.C1_0PackageIdentifier
- Distribution.Package: instance GHC.Generics.Constructor Distribution.Package.C1_0PackageKey
- Distribution.Package: instance GHC.Generics.Constructor Distribution.Package.C1_0PackageName
- Distribution.Package: instance GHC.Generics.Constructor Distribution.Package.C1_1PackageKey
- Distribution.Package: instance GHC.Generics.Datatype Distribution.Package.D1Dependency
- Distribution.Package: instance GHC.Generics.Datatype Distribution.Package.D1InstalledPackageId
- Distribution.Package: instance GHC.Generics.Datatype Distribution.Package.D1PackageIdentifier
- Distribution.Package: instance GHC.Generics.Datatype Distribution.Package.D1PackageKey
- Distribution.Package: instance GHC.Generics.Datatype Distribution.Package.D1PackageName
- Distribution.Package: instance GHC.Generics.Generic Distribution.Package.InstalledPackageId
- Distribution.Package: instance GHC.Generics.Generic Distribution.Package.PackageKey
- Distribution.Package: instance GHC.Generics.Selector Distribution.Package.S1_0_0PackageIdentifier
- Distribution.Package: instance GHC.Generics.Selector Distribution.Package.S1_0_0PackageName
- Distribution.Package: instance GHC.Generics.Selector Distribution.Package.S1_0_1PackageIdentifier
- Distribution.Package: instance GHC.Read.Read Distribution.Package.InstalledPackageId
- Distribution.Package: instance GHC.Read.Read Distribution.Package.PackageKey
- Distribution.Package: instance GHC.Show.Show Distribution.Package.InstalledPackageId
- Distribution.Package: instance GHC.Show.Show Distribution.Package.PackageKey
- Distribution.Package: mkPackageKey :: Bool -> PackageId -> [PackageKey] -> [(ModuleName, (PackageKey, ModuleName))] -> PackageKey
- Distribution.Package: newtype InstalledPackageId
- Distribution.Package: packageKeyHash :: PackageKey -> String
- Distribution.Package: packageKeyLibraryName :: PackageId -> PackageKey -> String
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0Benchmark
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0BenchmarkInterface
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0BenchmarkType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0BuildType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0Executable
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0FlagName
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0Library
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0ModuleReexport
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0ModuleRenaming
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0RepoKind
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0RepoType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0SourceRepo
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0TestSuite
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0TestSuiteInterface
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_0TestType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_1BenchmarkInterface
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_1BenchmarkType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_1BuildType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_1RepoKind
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_1RepoType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_1TestSuiteInterface
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_1TestType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_2BuildType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_2RepoKind
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_2RepoType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_2TestSuiteInterface
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_2TestType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_3BuildType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_3RepoType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_4BuildType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_4RepoType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_5RepoType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_6RepoType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_7RepoType
- Distribution.PackageDescription: instance GHC.Generics.Constructor Distribution.PackageDescription.C1_8RepoType
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1Benchmark
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1BenchmarkInterface
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1BenchmarkType
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1BuildType
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1Executable
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1FlagName
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1Library
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1ModuleReexport
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1ModuleRenaming
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1RepoKind
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1RepoType
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1SourceRepo
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1TestSuite
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1TestSuiteInterface
- Distribution.PackageDescription: instance GHC.Generics.Datatype Distribution.PackageDescription.D1TestType
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_0Benchmark
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_0BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_0Executable
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_0Library
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_0ModuleReexport
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_0PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_0SourceRepo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_0TestSuite
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_10BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_10PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_11BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_11PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_12BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_12PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_13BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_13PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_14BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_14PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_15BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_15PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_16BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_16PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_17BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_17PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_18BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_18PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_19BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_19PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_1Benchmark
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_1BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_1Executable
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_1Library
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_1ModuleReexport
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_1PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_1SourceRepo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_1TestSuite
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_20BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_20PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_21BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_21PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_22BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_22PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_23BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_23PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_24BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_24PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_25BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_25PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_26BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_26PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_27BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_27PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_2Benchmark
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_2BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_2Executable
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_2Library
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_2ModuleReexport
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_2PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_2SourceRepo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_2TestSuite
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_3Benchmark
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_3BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_3Library
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_3PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_3SourceRepo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_3TestSuite
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_4BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_4Library
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_4PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_4SourceRepo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_5BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_5Library
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_5PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_5SourceRepo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_6BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_6PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_6SourceRepo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_7BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_7PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_8BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_8PackageDescription
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_9BuildInfo
- Distribution.PackageDescription: instance GHC.Generics.Selector Distribution.PackageDescription.S1_0_9PackageDescription
- Distribution.PackageDescription.Configuration: instance GHC.Base.Monoid d => GHC.Base.Monoid (Distribution.PackageDescription.Configuration.DepTestRslt d)
- Distribution.PackageDescription.Parse: instance (GHC.Base.Monad m, GHC.Base.Functor m) => GHC.Base.Applicative (Distribution.PackageDescription.Parse.StT s m)
- Distribution.PackageDescription.Parse: instance Data.Data.Data Distribution.PackageDescription.Parse.DependencyWithRenaming
- Distribution.PackageDescription.Parse: instance Distribution.Text.Text Distribution.PackageDescription.Parse.DependencyWithRenaming
- Distribution.PackageDescription.Parse: instance GHC.Classes.Eq Distribution.PackageDescription.Parse.DependencyWithRenaming
- Distribution.PackageDescription.Parse: instance GHC.Read.Read Distribution.PackageDescription.Parse.DependencyWithRenaming
- Distribution.PackageDescription.Parse: instance GHC.Show.Show Distribution.PackageDescription.Parse.DependencyWithRenaming
- Distribution.Simple.BuildTarget: BuildTargetAmbigious :: UserBuildTarget -> [(UserBuildTarget, BuildTarget)] -> BuildTargetProblem
- Distribution.Simple.BuildTarget: instance GHC.Show.Show a => GHC.Show.Show (Distribution.Simple.BuildTarget.MaybeAmbigious a)
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_0Compiler
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_0DebugInfoLevel
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_0OptimisationLevel
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_0PackageDB
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_1DebugInfoLevel
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_1OptimisationLevel
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_1PackageDB
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_2DebugInfoLevel
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_2OptimisationLevel
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_2PackageDB
- Distribution.Simple.Compiler: instance GHC.Generics.Constructor Distribution.Simple.Compiler.C1_3DebugInfoLevel
- Distribution.Simple.Compiler: instance GHC.Generics.Datatype Distribution.Simple.Compiler.D1Compiler
- Distribution.Simple.Compiler: instance GHC.Generics.Datatype Distribution.Simple.Compiler.D1DebugInfoLevel
- Distribution.Simple.Compiler: instance GHC.Generics.Datatype Distribution.Simple.Compiler.D1OptimisationLevel
- Distribution.Simple.Compiler: instance GHC.Generics.Datatype Distribution.Simple.Compiler.D1PackageDB
- Distribution.Simple.Compiler: instance GHC.Generics.Selector Distribution.Simple.Compiler.S1_0_0Compiler
- Distribution.Simple.Compiler: instance GHC.Generics.Selector Distribution.Simple.Compiler.S1_0_1Compiler
- Distribution.Simple.Compiler: instance GHC.Generics.Selector Distribution.Simple.Compiler.S1_0_2Compiler
- Distribution.Simple.Compiler: instance GHC.Generics.Selector Distribution.Simple.Compiler.S1_0_3Compiler
- Distribution.Simple.Compiler: instance GHC.Generics.Selector Distribution.Simple.Compiler.S1_0_4Compiler
- Distribution.Simple.Compiler: instance GHC.Generics.Selector Distribution.Simple.Compiler.S1_0_5Compiler
- Distribution.Simple.InstallDirs: PkgKeyVar :: PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Base.Monoid dir => GHC.Base.Monoid (Distribution.Simple.InstallDirs.InstallDirs dir)
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_0InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_0PathComponent
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_0PathTemplate
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_0PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_10PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_11PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_12PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_13PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_14PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_15PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_16PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_17PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_18PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_19PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_1PathComponent
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_1PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_20PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_21PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_2PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_3PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_4PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_5PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_6PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_7PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_8PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Constructor Distribution.Simple.InstallDirs.C1_9PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Datatype Distribution.Simple.InstallDirs.D1InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Datatype Distribution.Simple.InstallDirs.D1PathComponent
- Distribution.Simple.InstallDirs: instance GHC.Generics.Datatype Distribution.Simple.InstallDirs.D1PathTemplate
- Distribution.Simple.InstallDirs: instance GHC.Generics.Datatype Distribution.Simple.InstallDirs.D1PathTemplateVariable
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_0InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_10InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_11InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_12InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_13InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_1InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_2InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_3InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_4InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_5InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_6InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_7InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_8InstallDirs
- Distribution.Simple.InstallDirs: instance GHC.Generics.Selector Distribution.Simple.InstallDirs.S1_0_9InstallDirs
- Distribution.Simple.LocalBuildInfo: LibraryName :: String -> LibraryName
- Distribution.Simple.LocalBuildInfo: [componentLibraries] :: ComponentLocalBuildInfo -> [LibraryName]
- Distribution.Simple.LocalBuildInfo: [instantiatedWith] :: LocalBuildInfo -> [(ModuleName, (InstalledPackageInfo, ModuleName))]
- Distribution.Simple.LocalBuildInfo: [pkgKey] :: LocalBuildInfo -> PackageKey
- Distribution.Simple.LocalBuildInfo: data LibraryName
- Distribution.Simple.LocalBuildInfo: inplacePackageId :: PackageId -> InstalledPackageId
- Distribution.Simple.LocalBuildInfo: instance Data.Binary.Class.Binary Distribution.Simple.LocalBuildInfo.LibraryName
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Constructor Distribution.Simple.LocalBuildInfo.C1_0ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Constructor Distribution.Simple.LocalBuildInfo.C1_0ComponentName
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Constructor Distribution.Simple.LocalBuildInfo.C1_0LibraryName
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Constructor Distribution.Simple.LocalBuildInfo.C1_0LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Constructor Distribution.Simple.LocalBuildInfo.C1_1ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Constructor Distribution.Simple.LocalBuildInfo.C1_1ComponentName
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Constructor Distribution.Simple.LocalBuildInfo.C1_2ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Constructor Distribution.Simple.LocalBuildInfo.C1_2ComponentName
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Constructor Distribution.Simple.LocalBuildInfo.C1_3ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Constructor Distribution.Simple.LocalBuildInfo.C1_3ComponentName
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Datatype Distribution.Simple.LocalBuildInfo.D1ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Datatype Distribution.Simple.LocalBuildInfo.D1ComponentName
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Datatype Distribution.Simple.LocalBuildInfo.D1LibraryName
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Datatype Distribution.Simple.LocalBuildInfo.D1LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Generic Distribution.Simple.LocalBuildInfo.LibraryName
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_0ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_0LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_10LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_11LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_12LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_13LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_14LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_15LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_16LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_17LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_18LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_19LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_1ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_1LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_20LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_21LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_22LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_23LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_24LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_25LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_26LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_27LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_2ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_2LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_3ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_3LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_4LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_5LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_6LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_7LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_8LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_0_9LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_1_0ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_1_1ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_2_0ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_2_1ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_3_0ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Generics.Selector Distribution.Simple.LocalBuildInfo.S1_3_1ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: instance GHC.Read.Read Distribution.Simple.LocalBuildInfo.LibraryName
- Distribution.Simple.LocalBuildInfo: instance GHC.Show.Show Distribution.Simple.LocalBuildInfo.LibraryName
- Distribution.Simple.PackageIndex: brokenPackages' :: PackageInstalled a => FakeMap -> PackageIndex a -> [(a, [InstalledPackageId])]
- Distribution.Simple.PackageIndex: dependencyClosure' :: PackageInstalled a => FakeMap -> PackageIndex a -> [InstalledPackageId] -> Either (PackageIndex a) [(a, [InstalledPackageId])]
- Distribution.Simple.PackageIndex: dependencyCycles' :: PackageInstalled a => FakeMap -> PackageIndex a -> [[a]]
- Distribution.Simple.PackageIndex: dependencyGraph' :: PackageInstalled a => FakeMap -> PackageIndex a -> (Graph, Vertex -> a, InstalledPackageId -> Maybe Vertex)
- Distribution.Simple.PackageIndex: dependencyInconsistencies' :: PackageInstalled a => FakeMap -> PackageIndex a -> [(PackageName, [(PackageId, Version)])]
- Distribution.Simple.PackageIndex: fakeLookupInstalledPackageId :: PackageInstalled a => FakeMap -> PackageIndex a -> InstalledPackageId -> Maybe a
- Distribution.Simple.PackageIndex: instance Distribution.Package.PackageInstalled a => GHC.Base.Monoid (Distribution.Simple.PackageIndex.PackageIndex a)
- Distribution.Simple.PackageIndex: instance GHC.Generics.Constructor Distribution.Simple.PackageIndex.C1_0PackageIndex
- Distribution.Simple.PackageIndex: instance GHC.Generics.Datatype Distribution.Simple.PackageIndex.D1PackageIndex
- Distribution.Simple.PackageIndex: reverseDependencyClosure' :: PackageInstalled a => FakeMap -> PackageIndex a -> [InstalledPackageId] -> [a]
- Distribution.Simple.PackageIndex: type FakeMap = Map InstalledPackageId InstalledPackageId
- Distribution.Simple.Program.GHC: [ghcOptPackageKey] :: GhcOptions -> Flag PackageKey
- Distribution.Simple.Program.GHC: [ghcOptSigOf] :: GhcOptions -> [(ModuleName, (PackageKey, ModuleName))]
- Distribution.Simple.Program.HcPkg: [useSingleFileDb] :: HcPkgInfo -> Bool
- Distribution.Simple.Program.Types: instance GHC.Generics.Constructor Distribution.Simple.Program.Types.C1_0ConfiguredProgram
- Distribution.Simple.Program.Types: instance GHC.Generics.Constructor Distribution.Simple.Program.Types.C1_0ProgramLocation
- Distribution.Simple.Program.Types: instance GHC.Generics.Constructor Distribution.Simple.Program.Types.C1_1ProgramLocation
- Distribution.Simple.Program.Types: instance GHC.Generics.Datatype Distribution.Simple.Program.Types.D1ConfiguredProgram
- Distribution.Simple.Program.Types: instance GHC.Generics.Datatype Distribution.Simple.Program.Types.D1ProgramLocation
- Distribution.Simple.Program.Types: instance GHC.Generics.Selector Distribution.Simple.Program.Types.S1_0_0ConfiguredProgram
- Distribution.Simple.Program.Types: instance GHC.Generics.Selector Distribution.Simple.Program.Types.S1_0_0ProgramLocation
- Distribution.Simple.Program.Types: instance GHC.Generics.Selector Distribution.Simple.Program.Types.S1_0_1ConfiguredProgram
- Distribution.Simple.Program.Types: instance GHC.Generics.Selector Distribution.Simple.Program.Types.S1_0_2ConfiguredProgram
- Distribution.Simple.Program.Types: instance GHC.Generics.Selector Distribution.Simple.Program.Types.S1_0_3ConfiguredProgram
- Distribution.Simple.Program.Types: instance GHC.Generics.Selector Distribution.Simple.Program.Types.S1_0_4ConfiguredProgram
- Distribution.Simple.Program.Types: instance GHC.Generics.Selector Distribution.Simple.Program.Types.S1_0_5ConfiguredProgram
- Distribution.Simple.Program.Types: instance GHC.Generics.Selector Distribution.Simple.Program.Types.S1_0_6ConfiguredProgram
- Distribution.Simple.Program.Types: instance GHC.Generics.Selector Distribution.Simple.Program.Types.S1_1_0ProgramLocation
- Distribution.Simple.Setup: [configInstantiateWith] :: ConfigFlags -> [(ModuleName, (InstalledPackageId, ModuleName))]
- Distribution.Simple.Setup: [configPrograms] :: ConfigFlags -> ProgramConfiguration
- Distribution.Simple.Setup: instance GHC.Generics.Constructor Distribution.Simple.Setup.C1_0ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Constructor Distribution.Simple.Setup.C1_0Flag
- Distribution.Simple.Setup: instance GHC.Generics.Constructor Distribution.Simple.Setup.C1_1Flag
- Distribution.Simple.Setup: instance GHC.Generics.Datatype Distribution.Simple.Setup.D1ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Datatype Distribution.Simple.Setup.D1Flag
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_0ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_10ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_11ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_12ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_13ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_14ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_15ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_16ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_17ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_18ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_19ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_1ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_20ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_21ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_22ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_23ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_24ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_25ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_26ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_27ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_28ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_29ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_2ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_30ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_31ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_32ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_33ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_34ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_35ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_36ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_37ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_38ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_39ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_3ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_4ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_5ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_6ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_7ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_8ConfigFlags
- Distribution.Simple.Setup: instance GHC.Generics.Selector Distribution.Simple.Setup.S1_0_9ConfigFlags
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_0Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_0OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_0Platform
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_10Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_10OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_11Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_11OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_12Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_12OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_13Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_13OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_14Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_14OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_15Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_16Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_1Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_1OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_2Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_2OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_3Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_3OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_4Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_4OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_5Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_5OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_6Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_6OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_7Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_7OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_8Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_8OS
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_9Arch
- Distribution.System: instance GHC.Generics.Constructor Distribution.System.C1_9OS
- Distribution.System: instance GHC.Generics.Datatype Distribution.System.D1Arch
- Distribution.System: instance GHC.Generics.Datatype Distribution.System.D1OS
- Distribution.System: instance GHC.Generics.Datatype Distribution.System.D1Platform
- Distribution.Verbosity: instance GHC.Generics.Constructor Distribution.Verbosity.C1_0Verbosity
- Distribution.Verbosity: instance GHC.Generics.Constructor Distribution.Verbosity.C1_1Verbosity
- Distribution.Verbosity: instance GHC.Generics.Constructor Distribution.Verbosity.C1_2Verbosity
- Distribution.Verbosity: instance GHC.Generics.Constructor Distribution.Verbosity.C1_3Verbosity
- Distribution.Verbosity: instance GHC.Generics.Datatype Distribution.Verbosity.D1Verbosity
- Distribution.Version: instance Data.Binary.Class.Binary Data.Version.Version
- Distribution.Version: instance GHC.Generics.Constructor Distribution.Version.C1_0VersionRange
- Distribution.Version: instance GHC.Generics.Constructor Distribution.Version.C1_1VersionRange
- Distribution.Version: instance GHC.Generics.Constructor Distribution.Version.C1_2VersionRange
- Distribution.Version: instance GHC.Generics.Constructor Distribution.Version.C1_3VersionRange
- Distribution.Version: instance GHC.Generics.Constructor Distribution.Version.C1_4VersionRange
- Distribution.Version: instance GHC.Generics.Constructor Distribution.Version.C1_5VersionRange
- Distribution.Version: instance GHC.Generics.Constructor Distribution.Version.C1_6VersionRange
- Distribution.Version: instance GHC.Generics.Constructor Distribution.Version.C1_7VersionRange
- Distribution.Version: instance GHC.Generics.Datatype Distribution.Version.D1VersionRange
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_0Extension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_0KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_0Language
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_100KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_101KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_102KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_103KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_104KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_105KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_10KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_11KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_12KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_13KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_14KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_15KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_16KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_17KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_18KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_19KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_1Extension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_1KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_1Language
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_20KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_21KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_22KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_23KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_24KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_25KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_26KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_27KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_28KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_29KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_2Extension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_2KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_2Language
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_30KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_31KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_32KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_33KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_34KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_35KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_36KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_37KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_38KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_39KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_3KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_40KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_41KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_42KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_43KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_44KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_45KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_46KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_47KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_48KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_49KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_4KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_50KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_51KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_52KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_53KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_54KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_55KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_56KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_57KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_58KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_59KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_5KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_60KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_61KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_62KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_63KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_64KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_65KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_66KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_67KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_68KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_69KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_6KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_70KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_71KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_72KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_73KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_74KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_75KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_76KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_77KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_78KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_79KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_7KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_80KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_81KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_82KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_83KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_84KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_85KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_86KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_87KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_88KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_89KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_8KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_90KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_91KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_92KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_93KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_94KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_95KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_96KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_97KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_98KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_99KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Constructor Language.Haskell.Extension.C1_9KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Datatype Language.Haskell.Extension.D1Extension
- Language.Haskell.Extension: instance GHC.Generics.Datatype Language.Haskell.Extension.D1KnownExtension
- Language.Haskell.Extension: instance GHC.Generics.Datatype Language.Haskell.Extension.D1Language
+ Distribution.Compat.Binary: decodeOrFailIO :: Binary a => ByteString -> IO (Either String a)
+ Distribution.Compat.ReadP: infixr 5 <++
+ Distribution.Compat.ReadP: instance Control.Monad.Fail.MonadFail (Distribution.Compat.ReadP.P s)
+ Distribution.Compat.ReadP: instance Control.Monad.Fail.MonadFail (Distribution.Compat.ReadP.Parser r s)
+ Distribution.Compat.Semigroup: (<>) :: a -> a -> a
+ Distribution.Compat.Semigroup: All :: Bool -> All
+ Distribution.Compat.Semigroup: Any :: Bool -> Any
+ Distribution.Compat.Semigroup: Last' :: Maybe a -> Last' a
+ Distribution.Compat.Semigroup: [getAll] :: All -> Bool
+ Distribution.Compat.Semigroup: [getAny] :: Any -> Bool
+ Distribution.Compat.Semigroup: [getLast'] :: Last' a -> Maybe a
+ Distribution.Compat.Semigroup: class Monoid a
+ Distribution.Compat.Semigroup: class Semigroup a
+ Distribution.Compat.Semigroup: gmappend :: (Generic a, GSemigroup (Rep a)) => a -> a -> a
+ Distribution.Compat.Semigroup: gmempty :: (Generic a, GMonoid (Rep a)) => a
+ Distribution.Compat.Semigroup: instance (Data.Semigroup.Semigroup a, GHC.Base.Monoid a) => Distribution.Compat.Semigroup.GMonoid (GHC.Generics.K1 i a)
+ Distribution.Compat.Semigroup: instance (Distribution.Compat.Semigroup.GMonoid f, Distribution.Compat.Semigroup.GMonoid g) => Distribution.Compat.Semigroup.GMonoid (f GHC.Generics.:*: g)
+ Distribution.Compat.Semigroup: instance (Distribution.Compat.Semigroup.GSemigroup f, Distribution.Compat.Semigroup.GSemigroup g) => Distribution.Compat.Semigroup.GSemigroup (f GHC.Generics.:*: g)
+ Distribution.Compat.Semigroup: instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Distribution.Compat.Semigroup.Last' a)
+ Distribution.Compat.Semigroup: instance Data.Semigroup.Semigroup (Distribution.Compat.Semigroup.Last' a)
+ Distribution.Compat.Semigroup: instance Data.Semigroup.Semigroup a => Distribution.Compat.Semigroup.GSemigroup (GHC.Generics.K1 i a)
+ Distribution.Compat.Semigroup: instance Distribution.Compat.Semigroup.GMonoid f => Distribution.Compat.Semigroup.GMonoid (GHC.Generics.M1 i c f)
+ Distribution.Compat.Semigroup: instance Distribution.Compat.Semigroup.GSemigroup f => Distribution.Compat.Semigroup.GSemigroup (GHC.Generics.M1 i c f)
+ Distribution.Compat.Semigroup: instance GHC.Base.Applicative Distribution.Compat.Semigroup.Last'
+ Distribution.Compat.Semigroup: instance GHC.Base.Functor Distribution.Compat.Semigroup.Last'
+ Distribution.Compat.Semigroup: instance GHC.Base.Monoid (Distribution.Compat.Semigroup.Last' a)
+ Distribution.Compat.Semigroup: instance GHC.Classes.Eq a => GHC.Classes.Eq (Distribution.Compat.Semigroup.Last' a)
+ Distribution.Compat.Semigroup: instance GHC.Classes.Ord a => GHC.Classes.Ord (Distribution.Compat.Semigroup.Last' a)
+ Distribution.Compat.Semigroup: instance GHC.Generics.Generic (Distribution.Compat.Semigroup.Last' a)
+ Distribution.Compat.Semigroup: instance GHC.Read.Read a => GHC.Read.Read (Distribution.Compat.Semigroup.Last' a)
+ Distribution.Compat.Semigroup: instance GHC.Show.Show a => GHC.Show.Show (Distribution.Compat.Semigroup.Last' a)
+ Distribution.Compat.Semigroup: mappend :: a -> a -> a
+ Distribution.Compat.Semigroup: mconcat :: [a] -> a
+ Distribution.Compat.Semigroup: mempty :: a
+ Distribution.Compat.Semigroup: newtype All :: *
+ Distribution.Compat.Semigroup: newtype Any :: *
+ Distribution.Compat.Semigroup: newtype Last' a
+ Distribution.Compiler: instance GHC.Classes.Eq Distribution.Compiler.AbiTag
+ Distribution.InstalledPackageInfo: [abiHash] :: InstalledPackageInfo -> AbiHash
+ Distribution.InstalledPackageInfo: [compatPackageKey] :: InstalledPackageInfo -> String
+ Distribution.InstalledPackageInfo: [installedUnitId] :: InstalledPackageInfo -> UnitId
+ Distribution.InstalledPackageInfo: data InstalledPackageInfo
+ Distribution.InstalledPackageInfo: installedComponentId :: InstalledPackageInfo -> ComponentId
+ Distribution.InstalledPackageInfo: installedPackageId :: InstalledPackageInfo -> UnitId
+ Distribution.InstalledPackageInfo: instance Data.Binary.Class.Binary Distribution.InstalledPackageInfo.InstalledPackageInfo
+ Distribution.InstalledPackageInfo: instance Distribution.Package.HasUnitId Distribution.InstalledPackageInfo.InstalledPackageInfo
+ Distribution.InstalledPackageInfo: instance Distribution.Package.Package Distribution.InstalledPackageInfo.InstalledPackageInfo
+ Distribution.InstalledPackageInfo: instance Distribution.Package.PackageInstalled Distribution.InstalledPackageInfo.InstalledPackageInfo
+ Distribution.InstalledPackageInfo: instance GHC.Classes.Eq Distribution.InstalledPackageInfo.ExposedModule
+ Distribution.InstalledPackageInfo: instance GHC.Classes.Eq Distribution.InstalledPackageInfo.InstalledPackageInfo
+ Distribution.InstalledPackageInfo: instance GHC.Generics.Generic Distribution.InstalledPackageInfo.InstalledPackageInfo
+ Distribution.InstalledPackageInfo: instance GHC.Read.Read Distribution.InstalledPackageInfo.InstalledPackageInfo
+ Distribution.InstalledPackageInfo: instance GHC.Show.Show Distribution.InstalledPackageInfo.InstalledPackageInfo
+ Distribution.Package: AbiHash :: String -> AbiHash
+ Distribution.Package: ComponentId :: String -> ComponentId
+ Distribution.Package: SimpleUnitId :: ComponentId -> UnitId
+ Distribution.Package: class Package pkg => HasUnitId pkg
+ Distribution.Package: data ComponentId
+ Distribution.Package: getHSLibraryName :: UnitId -> String
+ Distribution.Package: installedUnitId :: HasUnitId pkg => pkg -> UnitId
+ Distribution.Package: instance Control.DeepSeq.NFData Distribution.Package.ComponentId
+ Distribution.Package: instance Control.DeepSeq.NFData Distribution.Package.UnitId
+ Distribution.Package: instance Data.Binary.Class.Binary Distribution.Package.AbiHash
+ Distribution.Package: instance Data.Binary.Class.Binary Distribution.Package.ComponentId
+ Distribution.Package: instance Data.Binary.Class.Binary Distribution.Package.UnitId
+ Distribution.Package: instance Data.Data.Data Distribution.Package.ComponentId
+ Distribution.Package: instance Data.Data.Data Distribution.Package.UnitId
+ Distribution.Package: instance Distribution.Text.Text Distribution.Package.AbiHash
+ Distribution.Package: instance Distribution.Text.Text Distribution.Package.ComponentId
+ Distribution.Package: instance Distribution.Text.Text Distribution.Package.UnitId
+ Distribution.Package: instance GHC.Classes.Eq Distribution.Package.AbiHash
+ Distribution.Package: instance GHC.Classes.Eq Distribution.Package.ComponentId
+ Distribution.Package: instance GHC.Classes.Eq Distribution.Package.UnitId
+ Distribution.Package: instance GHC.Classes.Ord Distribution.Package.ComponentId
+ Distribution.Package: instance GHC.Classes.Ord Distribution.Package.UnitId
+ Distribution.Package: instance GHC.Generics.Generic Distribution.Package.AbiHash
+ Distribution.Package: instance GHC.Generics.Generic Distribution.Package.ComponentId
+ Distribution.Package: instance GHC.Generics.Generic Distribution.Package.UnitId
+ Distribution.Package: instance GHC.Read.Read Distribution.Package.AbiHash
+ Distribution.Package: instance GHC.Read.Read Distribution.Package.ComponentId
+ Distribution.Package: instance GHC.Read.Read Distribution.Package.UnitId
+ Distribution.Package: instance GHC.Show.Show Distribution.Package.AbiHash
+ Distribution.Package: instance GHC.Show.Show Distribution.Package.ComponentId
+ Distribution.Package: instance GHC.Show.Show Distribution.Package.UnitId
+ Distribution.Package: mkLegacyUnitId :: PackageId -> UnitId
+ Distribution.Package: mkUnitId :: String -> UnitId
+ Distribution.Package: newtype AbiHash
+ Distribution.Package: newtype UnitId
+ Distribution.Package: type InstalledPackageId = UnitId
+ Distribution.PackageDescription: SetupBuildInfo :: [Dependency] -> Bool -> SetupBuildInfo
+ Distribution.PackageDescription: [defaultSetupDepends] :: SetupBuildInfo -> Bool
+ Distribution.PackageDescription: [extraFrameworkDirs] :: BuildInfo -> [String]
+ Distribution.PackageDescription: [setupBuildInfo] :: PackageDescription -> Maybe SetupBuildInfo
+ Distribution.PackageDescription: [setupDepends] :: SetupBuildInfo -> [Dependency]
+ Distribution.PackageDescription: cAnd :: Condition a -> Condition a -> Condition a
+ Distribution.PackageDescription: cNot :: Condition a -> Condition a
+ Distribution.PackageDescription: cOr :: Eq v => Condition v -> Condition v -> Condition v
+ Distribution.PackageDescription: data SetupBuildInfo
+ Distribution.PackageDescription: instance (Data.Binary.Class.Binary v, Data.Binary.Class.Binary c, Data.Binary.Class.Binary a) => Data.Binary.Class.Binary (Distribution.PackageDescription.CondTree v c a)
+ Distribution.PackageDescription: instance Data.Binary.Class.Binary Distribution.PackageDescription.ConfVar
+ Distribution.PackageDescription: instance Data.Binary.Class.Binary Distribution.PackageDescription.Flag
+ Distribution.PackageDescription: instance Data.Binary.Class.Binary Distribution.PackageDescription.GenericPackageDescription
+ Distribution.PackageDescription: instance Data.Binary.Class.Binary Distribution.PackageDescription.SetupBuildInfo
+ Distribution.PackageDescription: instance Data.Binary.Class.Binary c => Data.Binary.Class.Binary (Distribution.PackageDescription.Condition c)
+ Distribution.PackageDescription: instance Data.Data.Data Distribution.PackageDescription.SetupBuildInfo
+ Distribution.PackageDescription: instance Data.Foldable.Foldable Distribution.PackageDescription.Condition
+ Distribution.PackageDescription: instance Data.Semigroup.Semigroup (Distribution.PackageDescription.Condition a)
+ Distribution.PackageDescription: instance Data.Semigroup.Semigroup Distribution.PackageDescription.Benchmark
+ Distribution.PackageDescription: instance Data.Semigroup.Semigroup Distribution.PackageDescription.BenchmarkInterface
+ Distribution.PackageDescription: instance Data.Semigroup.Semigroup Distribution.PackageDescription.BuildInfo
+ Distribution.PackageDescription: instance Data.Semigroup.Semigroup Distribution.PackageDescription.Executable
+ Distribution.PackageDescription: instance Data.Semigroup.Semigroup Distribution.PackageDescription.Library
+ Distribution.PackageDescription: instance Data.Semigroup.Semigroup Distribution.PackageDescription.ModuleRenaming
+ Distribution.PackageDescription: instance Data.Semigroup.Semigroup Distribution.PackageDescription.SetupBuildInfo
+ Distribution.PackageDescription: instance Data.Semigroup.Semigroup Distribution.PackageDescription.TestSuite
+ Distribution.PackageDescription: instance Data.Semigroup.Semigroup Distribution.PackageDescription.TestSuiteInterface
+ Distribution.PackageDescription: instance Data.Traversable.Traversable Distribution.PackageDescription.Condition
+ Distribution.PackageDescription: instance GHC.Base.Alternative Distribution.PackageDescription.Condition
+ Distribution.PackageDescription: instance GHC.Base.Applicative Distribution.PackageDescription.Condition
+ Distribution.PackageDescription: instance GHC.Base.Functor Distribution.PackageDescription.Condition
+ Distribution.PackageDescription: instance GHC.Base.Monad Distribution.PackageDescription.Condition
+ Distribution.PackageDescription: instance GHC.Base.MonadPlus Distribution.PackageDescription.Condition
+ Distribution.PackageDescription: instance GHC.Base.Monoid (Distribution.PackageDescription.Condition a)
+ Distribution.PackageDescription: instance GHC.Base.Monoid Distribution.PackageDescription.SetupBuildInfo
+ Distribution.PackageDescription: instance GHC.Classes.Eq Distribution.PackageDescription.SetupBuildInfo
+ Distribution.PackageDescription: instance GHC.Generics.Generic (Distribution.PackageDescription.CondTree v c a)
+ Distribution.PackageDescription: instance GHC.Generics.Generic (Distribution.PackageDescription.Condition c)
+ Distribution.PackageDescription: instance GHC.Generics.Generic Distribution.PackageDescription.ConfVar
+ Distribution.PackageDescription: instance GHC.Generics.Generic Distribution.PackageDescription.Flag
+ Distribution.PackageDescription: instance GHC.Generics.Generic Distribution.PackageDescription.GenericPackageDescription
+ Distribution.PackageDescription: instance GHC.Generics.Generic Distribution.PackageDescription.SetupBuildInfo
+ Distribution.PackageDescription: instance GHC.Read.Read Distribution.PackageDescription.SetupBuildInfo
+ Distribution.PackageDescription: instance GHC.Show.Show Distribution.PackageDescription.SetupBuildInfo
+ Distribution.PackageDescription.Check: PackageDistSuspiciousWarn :: String -> PackageCheck
+ Distribution.PackageDescription.Check: [getDirectoryContents] :: CheckPackageContentOps m -> FilePath -> m [FilePath]
+ Distribution.PackageDescription.Check: [getFileContents] :: CheckPackageContentOps m -> FilePath -> m String
+ Distribution.PackageDescription.Configuration: addBuildableCondition :: (Eq v, Monoid a, Monoid c) => (a -> BuildInfo) -> CondTree v c a -> CondTree v c a
+ Distribution.PackageDescription.Configuration: extractCondition :: Eq v => (a -> Bool) -> CondTree v c a -> Condition v
+ Distribution.PackageDescription.Configuration: extractConditions :: (BuildInfo -> Bool) -> GenericPackageDescription -> [Condition ConfVar]
+ Distribution.PackageDescription.Configuration: instance Data.Semigroup.Semigroup Distribution.PackageDescription.Configuration.DependencyMap
+ Distribution.PackageDescription.Configuration: instance Data.Semigroup.Semigroup Distribution.PackageDescription.Configuration.PDTagged
+ Distribution.PackageDescription.Configuration: instance Data.Semigroup.Semigroup d => Data.Semigroup.Semigroup (Distribution.PackageDescription.Configuration.DepTestRslt d)
+ Distribution.PackageDescription.Configuration: instance Data.Semigroup.Semigroup d => GHC.Base.Monoid (Distribution.PackageDescription.Configuration.DepTestRslt d)
+ Distribution.PackageDescription.Configuration: transformAllBuildDepends :: (Dependency -> Dependency) -> GenericPackageDescription -> GenericPackageDescription
+ Distribution.PackageDescription.Configuration: transformAllBuildInfos :: (BuildInfo -> BuildInfo) -> (SetupBuildInfo -> SetupBuildInfo) -> GenericPackageDescription -> GenericPackageDescription
+ Distribution.PackageDescription.Parse: instance GHC.Base.Monad m => GHC.Base.Applicative (Distribution.PackageDescription.Parse.StT s m)
+ Distribution.Simple.BuildTarget: BuildTargetAmbiguous :: UserBuildTarget -> [(UserBuildTarget, BuildTarget)] -> BuildTargetProblem
+ Distribution.Simple.BuildTarget: QL1 :: QualLevel
+ Distribution.Simple.BuildTarget: QL2 :: QualLevel
+ Distribution.Simple.BuildTarget: QL3 :: QualLevel
+ Distribution.Simple.BuildTarget: buildTargetComponentName :: BuildTarget -> ComponentName
+ Distribution.Simple.BuildTarget: data QualLevel
+ Distribution.Simple.BuildTarget: instance Data.Binary.Class.Binary Distribution.Simple.BuildTarget.BuildTarget
+ Distribution.Simple.BuildTarget: instance GHC.Generics.Generic Distribution.Simple.BuildTarget.BuildTarget
+ Distribution.Simple.BuildTarget: instance GHC.Show.Show a => GHC.Show.Show (Distribution.Simple.BuildTarget.MaybeAmbiguous a)
+ Distribution.Simple.BuildTarget: showBuildTarget :: QualLevel -> PackageId -> BuildTarget -> String
+ Distribution.Simple.BuildTarget: showUserBuildTarget :: UserBuildTarget -> String
+ Distribution.Simple.CCompiler: instance Data.Semigroup.Semigroup Distribution.Simple.CCompiler.CDialect
+ Distribution.Simple.Command: CommandSpec :: (CommandUI flags) -> (CommandUI flags -> Command action) -> CommandType -> CommandSpec action
+ Distribution.Simple.Command: HiddenCommand :: CommandType
+ Distribution.Simple.Command: NormalCommand :: CommandType
+ Distribution.Simple.Command: commandFromSpec :: CommandSpec a -> Command a
+ Distribution.Simple.Command: data CommandSpec action
+ Distribution.Simple.Command: data CommandType
+ Distribution.Simple.Compiler: ProfDetailAllFunctions :: ProfDetailLevel
+ Distribution.Simple.Compiler: ProfDetailDefault :: ProfDetailLevel
+ Distribution.Simple.Compiler: ProfDetailExportedFunctions :: ProfDetailLevel
+ Distribution.Simple.Compiler: ProfDetailNone :: ProfDetailLevel
+ Distribution.Simple.Compiler: ProfDetailOther :: String -> ProfDetailLevel
+ Distribution.Simple.Compiler: ProfDetailToplevelFunctions :: ProfDetailLevel
+ Distribution.Simple.Compiler: data ProfDetailLevel
+ Distribution.Simple.Compiler: flagToProfDetailLevel :: String -> ProfDetailLevel
+ Distribution.Simple.Compiler: instance Data.Binary.Class.Binary Distribution.Simple.Compiler.ProfDetailLevel
+ Distribution.Simple.Compiler: instance GHC.Classes.Eq Distribution.Simple.Compiler.Compiler
+ Distribution.Simple.Compiler: instance GHC.Classes.Eq Distribution.Simple.Compiler.ProfDetailLevel
+ Distribution.Simple.Compiler: instance GHC.Generics.Generic Distribution.Simple.Compiler.ProfDetailLevel
+ Distribution.Simple.Compiler: instance GHC.Read.Read Distribution.Simple.Compiler.ProfDetailLevel
+ Distribution.Simple.Compiler: instance GHC.Show.Show Distribution.Simple.Compiler.ProfDetailLevel
+ Distribution.Simple.Compiler: knownProfDetailLevels :: [(String, [String], ProfDetailLevel)]
+ Distribution.Simple.Compiler: showProfDetailLevel :: ProfDetailLevel -> String
+ Distribution.Simple.Compiler: unifiedIPIDRequired :: Compiler -> Bool
+ Distribution.Simple.Compiler: unitIdSupported :: Compiler -> Bool
+ Distribution.Simple.Configure: computeCompatPackageKey :: Compiler -> PackageIdentifier -> ComponentName -> UnitId -> (PackageName, String)
+ Distribution.Simple.Configure: computeComponentId :: PackageIdentifier -> ComponentName -> [ComponentId] -> FlagAssignment -> ComponentId
+ Distribution.Simple.Configure: findDistPref :: FilePath -> Flag FilePath -> IO FilePath
+ Distribution.Simple.Configure: findDistPrefOrDefault :: Flag FilePath -> IO FilePath
+ Distribution.Simple.Configure: getInstalledPackagesMonitorFiles :: Verbosity -> Compiler -> PackageDBStack -> ProgramConfiguration -> Platform -> IO [FilePath]
+ Distribution.Simple.Configure: relaxPackageDeps :: AllowNewer -> GenericPackageDescription -> GenericPackageDescription
+ Distribution.Simple.GHC: componentCcGhcOptions :: Verbosity -> LocalBuildInfo -> BuildInfo -> ComponentLocalBuildInfo -> FilePath -> FilePath -> GhcOptions
+ Distribution.Simple.GHC: getInstalledPackagesMonitorFiles :: Verbosity -> Platform -> ProgramConfiguration -> [PackageDB] -> IO [FilePath]
+ Distribution.Simple.Haddock: instance Data.Semigroup.Semigroup Distribution.Simple.Haddock.Directory
+ Distribution.Simple.Haddock: instance Data.Semigroup.Semigroup Distribution.Simple.Haddock.HaddockArgs
+ Distribution.Simple.Haddock: instance GHC.Generics.Generic Distribution.Simple.Haddock.HaddockArgs
+ Distribution.Simple.InstallDirs: instance (Data.Semigroup.Semigroup dir, GHC.Base.Monoid dir) => GHC.Base.Monoid (Distribution.Simple.InstallDirs.InstallDirs dir)
+ Distribution.Simple.InstallDirs: instance Data.Semigroup.Semigroup dir => Data.Semigroup.Semigroup (Distribution.Simple.InstallDirs.InstallDirs dir)
+ Distribution.Simple.InstallDirs: instance GHC.Classes.Eq dir => GHC.Classes.Eq (Distribution.Simple.InstallDirs.InstallDirs dir)
+ Distribution.Simple.LocalBuildInfo: [componentCompatPackageKey] :: ComponentLocalBuildInfo -> String
+ Distribution.Simple.LocalBuildInfo: [componentUnitId] :: ComponentLocalBuildInfo -> UnitId
+ Distribution.Simple.LocalBuildInfo: [flagAssignment] :: LocalBuildInfo -> FlagAssignment
+ Distribution.Simple.LocalBuildInfo: [withProfExeDetail] :: LocalBuildInfo -> ProfDetailLevel
+ Distribution.Simple.LocalBuildInfo: [withProfLibDetail] :: LocalBuildInfo -> ProfDetailLevel
+ Distribution.Simple.LocalBuildInfo: localCompatPackageKey :: LocalBuildInfo -> String
+ Distribution.Simple.LocalBuildInfo: localComponentId :: LocalBuildInfo -> ComponentId
+ Distribution.Simple.LocalBuildInfo: localUnitId :: LocalBuildInfo -> UnitId
+ Distribution.Simple.PackageIndex: deleteUnitId :: HasUnitId a => UnitId -> PackageIndex a -> PackageIndex a
+ Distribution.Simple.PackageIndex: instance Distribution.Package.HasUnitId a => Data.Semigroup.Semigroup (Distribution.Simple.PackageIndex.PackageIndex a)
+ Distribution.Simple.PackageIndex: instance Distribution.Package.HasUnitId a => GHC.Base.Monoid (Distribution.Simple.PackageIndex.PackageIndex a)
+ Distribution.Simple.PackageIndex: instance GHC.Classes.Eq a => GHC.Classes.Eq (Distribution.Simple.PackageIndex.PackageIndex a)
+ Distribution.Simple.PackageIndex: lookupUnitId :: PackageIndex a -> UnitId -> Maybe a
+ Distribution.Simple.PreProcess: preprocessExtras :: Component -> LocalBuildInfo -> IO [FilePath]
+ Distribution.Simple.Program: [programMonitorFiles] :: ConfiguredProgram -> [FilePath]
+ Distribution.Simple.Program: defaultProgramSearchPath :: ProgramSearchPath
+ Distribution.Simple.Program: findProgramOnSearchPath :: Verbosity -> ProgramSearchPath -> FilePath -> IO (Maybe (FilePath, [FilePath]))
+ Distribution.Simple.Program.Find: getSystemSearchPath :: IO [FilePath]
+ Distribution.Simple.Program.Find: instance Data.Binary.Class.Binary Distribution.Simple.Program.Find.ProgramSearchPathEntry
+ Distribution.Simple.Program.Find: instance GHC.Classes.Eq Distribution.Simple.Program.Find.ProgramSearchPathEntry
+ Distribution.Simple.Program.Find: instance GHC.Generics.Generic Distribution.Simple.Program.Find.ProgramSearchPathEntry
+ Distribution.Simple.Program.GHC: GhcProfAutoAll :: GhcProfAuto
+ Distribution.Simple.Program.GHC: GhcProfAutoExported :: GhcProfAuto
+ Distribution.Simple.Program.GHC: GhcProfAutoToplevel :: GhcProfAuto
+ Distribution.Simple.Program.GHC: [ghcOptLinkFrameworkDirs] :: GhcOptions -> NubListR String
+ Distribution.Simple.Program.GHC: [ghcOptProfilingAuto] :: GhcOptions -> Flag GhcProfAuto
+ Distribution.Simple.Program.GHC: [ghcOptThisUnitId] :: GhcOptions -> Flag String
+ Distribution.Simple.Program.GHC: data GhcProfAuto
+ Distribution.Simple.Program.GHC: instance Data.Semigroup.Semigroup Distribution.Simple.Program.GHC.GhcOptions
+ Distribution.Simple.Program.GHC: instance GHC.Classes.Eq Distribution.Simple.Program.GHC.GhcProfAuto
+ Distribution.Simple.Program.GHC: instance GHC.Generics.Generic Distribution.Simple.Program.GHC.GhcOptions
+ Distribution.Simple.Program.GHC: instance GHC.Show.Show Distribution.Simple.Program.GHC.GhcProfAuto
+ Distribution.Simple.Program.HcPkg: [nativeMultiInstance] :: HcPkgInfo -> Bool
+ Distribution.Simple.Program.HcPkg: [recacheMultiInstance] :: HcPkgInfo -> Bool
+ Distribution.Simple.Program.HcPkg: [requiresDirDbs] :: HcPkgInfo -> Bool
+ Distribution.Simple.Program.HcPkg: [supportsDirDbs] :: HcPkgInfo -> Bool
+ Distribution.Simple.Program.HcPkg: describe :: HcPkgInfo -> Verbosity -> PackageDBStack -> PackageId -> IO [InstalledPackageInfo]
+ Distribution.Simple.Program.HcPkg: describeInvocation :: HcPkgInfo -> Verbosity -> PackageDBStack -> PackageId -> ProgramInvocation
+ Distribution.Simple.Program.HcPkg: recache :: HcPkgInfo -> Verbosity -> PackageDB -> IO ()
+ Distribution.Simple.Program.HcPkg: recacheInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> ProgramInvocation
+ Distribution.Simple.Program.HcPkg: registerMultiInstance :: HcPkgInfo -> Verbosity -> PackageDBStack -> InstalledPackageInfo -> IO ()
+ Distribution.Simple.Program.HcPkg: registerMultiInstanceInvocation :: HcPkgInfo -> Verbosity -> PackageDBStack -> Either FilePath InstalledPackageInfo -> ProgramInvocation
+ Distribution.Simple.Program.Internal: stripExtractVersion :: String -> String
+ Distribution.Simple.Program.Types: [programMonitorFiles] :: ConfiguredProgram -> [FilePath]
+ Distribution.Simple.Register: createPackageDB :: Verbosity -> Compiler -> ProgramConfiguration -> Bool -> FilePath -> IO ()
+ Distribution.Simple.Register: deletePackageDB :: FilePath -> IO ()
+ Distribution.Simple.Register: doesPackageDBExist :: FilePath -> IO Bool
+ Distribution.Simple.Setup: AllowNewerAll :: AllowNewer
+ Distribution.Simple.Setup: AllowNewerDep :: PackageName -> AllowNewerDep
+ Distribution.Simple.Setup: AllowNewerDepScoped :: PackageName -> PackageName -> AllowNewerDep
+ Distribution.Simple.Setup: AllowNewerNone :: AllowNewer
+ Distribution.Simple.Setup: AllowNewerSome :: [AllowNewerDep] -> AllowNewer
+ Distribution.Simple.Setup: Direct :: TestShowDetails
+ Distribution.Simple.Setup: [configAllowNewer] :: ConfigFlags -> Maybe AllowNewer
+ Distribution.Simple.Setup: [configExtraFrameworkDirs] :: ConfigFlags -> [FilePath]
+ Distribution.Simple.Setup: [configIPID] :: ConfigFlags -> Flag String
+ Distribution.Simple.Setup: [configProfDetail] :: ConfigFlags -> Flag ProfDetailLevel
+ Distribution.Simple.Setup: [configProfLibDetail] :: ConfigFlags -> Flag ProfDetailLevel
+ Distribution.Simple.Setup: [configProf] :: ConfigFlags -> Flag Bool
+ Distribution.Simple.Setup: [configPrograms_] :: ConfigFlags -> Last' ProgramConfiguration
+ Distribution.Simple.Setup: [haddockForHackage] :: HaddockFlags -> Flag Bool
+ Distribution.Simple.Setup: configPrograms :: ConfigFlags -> ProgramConfiguration
+ Distribution.Simple.Setup: data AllowNewer
+ Distribution.Simple.Setup: data AllowNewerDep
+ Distribution.Simple.Setup: instance Data.Binary.Class.Binary Distribution.Simple.Setup.AllowNewer
+ Distribution.Simple.Setup: instance Data.Binary.Class.Binary Distribution.Simple.Setup.AllowNewerDep
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup (Distribution.Simple.Setup.Flag a)
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.AllowNewer
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.BenchmarkFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.BuildFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.CleanFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.ConfigFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.CopyFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.GlobalFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.HaddockFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.HscolourFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.InstallFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.RegisterFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.ReplFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.SDistFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.TestFlags
+ Distribution.Simple.Setup: instance Data.Semigroup.Semigroup Distribution.Simple.Setup.TestShowDetails
+ Distribution.Simple.Setup: instance Distribution.Text.Text Distribution.Simple.Setup.AllowNewerDep
+ Distribution.Simple.Setup: instance GHC.Base.Monoid Distribution.Simple.Setup.AllowNewer
+ Distribution.Simple.Setup: instance GHC.Classes.Eq Distribution.Simple.Setup.AllowNewer
+ Distribution.Simple.Setup: instance GHC.Classes.Eq Distribution.Simple.Setup.AllowNewerDep
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.AllowNewer
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.AllowNewerDep
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.BenchmarkFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.BuildFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.CleanFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.CopyFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.GlobalFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.HaddockFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.HscolourFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.InstallFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.RegisterFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.ReplFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.SDistFlags
+ Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.TestFlags
+ Distribution.Simple.Setup: instance GHC.Read.Read Distribution.Simple.Setup.AllowNewer
+ Distribution.Simple.Setup: instance GHC.Read.Read Distribution.Simple.Setup.AllowNewerDep
+ Distribution.Simple.Setup: instance GHC.Show.Show Distribution.Simple.Setup.AllowNewer
+ Distribution.Simple.Setup: instance GHC.Show.Show Distribution.Simple.Setup.AllowNewerDep
+ Distribution.Simple.Setup: isAllowNewer :: AllowNewer -> Bool
+ Distribution.Simple.Setup: optionDistPref :: (flags -> Flag FilePath) -> (Flag FilePath -> flags -> flags) -> ShowOrParseArgs -> OptionField flags
+ Distribution.Simple.Setup: readPToMaybe :: ReadP a a -> String -> Maybe a
+ Distribution.Simple.Setup: splitArgs :: String -> [String]
+ Distribution.Simple.UHC: inplacePackageDbPath :: LocalBuildInfo -> FilePath
+ Distribution.Simple.Utils: createProcessWithEnv :: Verbosity -> FilePath -> [String] -> Maybe FilePath -> Maybe [(String, String)] -> StdStream -> StdStream -> StdStream -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
+ Distribution.Simple.Utils: dropExeExtension :: FilePath -> FilePath
+ Distribution.Simple.Utils: exeExtensions :: [String]
+ Distribution.Simple.Utils: fileHasBOM :: FilePath -> IO Bool
+ Distribution.Simple.Utils: findAllFilesWithExtension :: [String] -> [FilePath] -> FilePath -> IO [FilePath]
+ Distribution.Simple.Utils: handleDoesNotExist :: a -> IO a -> IO a
+ Distribution.Simple.Utils: ignoreBOM :: String -> String
+ Distribution.Simple.Utils: safeTail :: [a] -> [a]
+ Distribution.Simple.Utils: startsWithBOM :: String -> Bool
+ Distribution.System: Android :: OS
+ Distribution.System: Hurd :: OS
+ Distribution.System: knownArches :: [Arch]
+ Distribution.System: knownOSs :: [OS]
+ Distribution.Text: defaultStyle :: Style
+ Distribution.Text: instance Distribution.Text.Text GHC.Types.Int
+ Distribution.Utils.NubList: instance GHC.Classes.Ord a => Data.Semigroup.Semigroup (Distribution.Utils.NubList.NubList a)
+ Distribution.Utils.NubList: instance GHC.Classes.Ord a => Data.Semigroup.Semigroup (Distribution.Utils.NubList.NubListR a)
+ Distribution.Version: hasLowerBound :: VersionRange -> Bool
+ Distribution.Version: hasUpperBound :: VersionRange -> Bool
+ Distribution.Version: invertVersionIntervals :: VersionIntervals -> VersionIntervals
+ Distribution.Version: invertVersionRange :: VersionRange -> VersionRange
+ Language.Haskell.Extension: ApplicativeDo :: KnownExtension
+ Language.Haskell.Extension: DeriveLift :: KnownExtension
+ Language.Haskell.Extension: DuplicateRecordFields :: KnownExtension
+ Language.Haskell.Extension: MonadFailDesugaring :: KnownExtension
+ Language.Haskell.Extension: OverloadedLabels :: KnownExtension
+ Language.Haskell.Extension: StaticPointers :: KnownExtension
+ Language.Haskell.Extension: Strict :: KnownExtension
+ Language.Haskell.Extension: StrictData :: KnownExtension
+ Language.Haskell.Extension: TemplateHaskellQuotes :: KnownExtension
+ Language.Haskell.Extension: TypeApplications :: KnownExtension
+ Language.Haskell.Extension: TypeInType :: KnownExtension
+ Language.Haskell.Extension: UndecidableSuperClasses :: KnownExtension
- Distribution.InstalledPackageInfo: ExposedModule :: ModuleName -> Maybe OriginalModule -> Maybe OriginalModule -> ExposedModule
+ Distribution.InstalledPackageInfo: ExposedModule :: ModuleName -> Maybe OriginalModule -> ExposedModule
- Distribution.InstalledPackageInfo: InstalledPackageInfo :: InstalledPackageId -> PackageId -> PackageKey -> License -> String -> String -> String -> String -> String -> String -> String -> String -> String -> Bool -> [ExposedModule] -> [(m, OriginalModule)] -> [m] -> Bool -> [FilePath] -> [FilePath] -> FilePath -> [String] -> [String] -> [String] -> [FilePath] -> [String] -> [InstalledPackageId] -> [String] -> [String] -> [FilePath] -> [String] -> [FilePath] -> [FilePath] -> Maybe FilePath -> InstalledPackageInfo_ m
+ Distribution.InstalledPackageInfo: InstalledPackageInfo :: PackageId -> UnitId -> String -> License -> String -> String -> String -> String -> String -> String -> String -> String -> String -> AbiHash -> Bool -> [ExposedModule] -> [ModuleName] -> Bool -> [FilePath] -> [FilePath] -> FilePath -> [String] -> [String] -> [String] -> [FilePath] -> [String] -> [UnitId] -> [String] -> [String] -> [FilePath] -> [String] -> [FilePath] -> [FilePath] -> Maybe FilePath -> InstalledPackageInfo
- Distribution.InstalledPackageInfo: OriginalModule :: InstalledPackageId -> ModuleName -> OriginalModule
+ Distribution.InstalledPackageInfo: OriginalModule :: UnitId -> ModuleName -> OriginalModule
- Distribution.InstalledPackageInfo: [author] :: InstalledPackageInfo_ m -> String
+ Distribution.InstalledPackageInfo: [author] :: InstalledPackageInfo -> String
- Distribution.InstalledPackageInfo: [category] :: InstalledPackageInfo_ m -> String
+ Distribution.InstalledPackageInfo: [category] :: InstalledPackageInfo -> String
- Distribution.InstalledPackageInfo: [ccOptions] :: InstalledPackageInfo_ m -> [String]
+ Distribution.InstalledPackageInfo: [ccOptions] :: InstalledPackageInfo -> [String]
- Distribution.InstalledPackageInfo: [copyright] :: InstalledPackageInfo_ m -> String
+ Distribution.InstalledPackageInfo: [copyright] :: InstalledPackageInfo -> String
- Distribution.InstalledPackageInfo: [dataDir] :: InstalledPackageInfo_ m -> FilePath
+ Distribution.InstalledPackageInfo: [dataDir] :: InstalledPackageInfo -> FilePath
- Distribution.InstalledPackageInfo: [depends] :: InstalledPackageInfo_ m -> [InstalledPackageId]
+ Distribution.InstalledPackageInfo: [depends] :: InstalledPackageInfo -> [UnitId]
- Distribution.InstalledPackageInfo: [description] :: InstalledPackageInfo_ m -> String
+ Distribution.InstalledPackageInfo: [description] :: InstalledPackageInfo -> String
- Distribution.InstalledPackageInfo: [exposedModules] :: InstalledPackageInfo_ m -> [ExposedModule]
+ Distribution.InstalledPackageInfo: [exposedModules] :: InstalledPackageInfo -> [ExposedModule]
- Distribution.InstalledPackageInfo: [exposed] :: InstalledPackageInfo_ m -> Bool
+ Distribution.InstalledPackageInfo: [exposed] :: InstalledPackageInfo -> Bool
- Distribution.InstalledPackageInfo: [extraGHCiLibraries] :: InstalledPackageInfo_ m -> [String]
+ Distribution.InstalledPackageInfo: [extraGHCiLibraries] :: InstalledPackageInfo -> [String]
- Distribution.InstalledPackageInfo: [extraLibraries] :: InstalledPackageInfo_ m -> [String]
+ Distribution.InstalledPackageInfo: [extraLibraries] :: InstalledPackageInfo -> [String]
- Distribution.InstalledPackageInfo: [frameworkDirs] :: InstalledPackageInfo_ m -> [FilePath]
+ Distribution.InstalledPackageInfo: [frameworkDirs] :: InstalledPackageInfo -> [FilePath]
- Distribution.InstalledPackageInfo: [frameworks] :: InstalledPackageInfo_ m -> [String]
+ Distribution.InstalledPackageInfo: [frameworks] :: InstalledPackageInfo -> [String]
- Distribution.InstalledPackageInfo: [haddockHTMLs] :: InstalledPackageInfo_ m -> [FilePath]
+ Distribution.InstalledPackageInfo: [haddockHTMLs] :: InstalledPackageInfo -> [FilePath]
- Distribution.InstalledPackageInfo: [haddockInterfaces] :: InstalledPackageInfo_ m -> [FilePath]
+ Distribution.InstalledPackageInfo: [haddockInterfaces] :: InstalledPackageInfo -> [FilePath]
- Distribution.InstalledPackageInfo: [hiddenModules] :: InstalledPackageInfo_ m -> [m]
+ Distribution.InstalledPackageInfo: [hiddenModules] :: InstalledPackageInfo -> [ModuleName]
- Distribution.InstalledPackageInfo: [homepage] :: InstalledPackageInfo_ m -> String
+ Distribution.InstalledPackageInfo: [homepage] :: InstalledPackageInfo -> String
- Distribution.InstalledPackageInfo: [hsLibraries] :: InstalledPackageInfo_ m -> [String]
+ Distribution.InstalledPackageInfo: [hsLibraries] :: InstalledPackageInfo -> [String]
- Distribution.InstalledPackageInfo: [importDirs] :: InstalledPackageInfo_ m -> [FilePath]
+ Distribution.InstalledPackageInfo: [importDirs] :: InstalledPackageInfo -> [FilePath]
- Distribution.InstalledPackageInfo: [includeDirs] :: InstalledPackageInfo_ m -> [FilePath]
+ Distribution.InstalledPackageInfo: [includeDirs] :: InstalledPackageInfo -> [FilePath]
- Distribution.InstalledPackageInfo: [includes] :: InstalledPackageInfo_ m -> [String]
+ Distribution.InstalledPackageInfo: [includes] :: InstalledPackageInfo -> [String]
- Distribution.InstalledPackageInfo: [ldOptions] :: InstalledPackageInfo_ m -> [String]
+ Distribution.InstalledPackageInfo: [ldOptions] :: InstalledPackageInfo -> [String]
- Distribution.InstalledPackageInfo: [libraryDirs] :: InstalledPackageInfo_ m -> [FilePath]
+ Distribution.InstalledPackageInfo: [libraryDirs] :: InstalledPackageInfo -> [FilePath]
- Distribution.InstalledPackageInfo: [license] :: InstalledPackageInfo_ m -> License
+ Distribution.InstalledPackageInfo: [license] :: InstalledPackageInfo -> License
- Distribution.InstalledPackageInfo: [maintainer] :: InstalledPackageInfo_ m -> String
+ Distribution.InstalledPackageInfo: [maintainer] :: InstalledPackageInfo -> String
- Distribution.InstalledPackageInfo: [originalPackageId] :: OriginalModule -> InstalledPackageId
+ Distribution.InstalledPackageInfo: [originalPackageId] :: OriginalModule -> UnitId
- Distribution.InstalledPackageInfo: [pkgRoot] :: InstalledPackageInfo_ m -> Maybe FilePath
+ Distribution.InstalledPackageInfo: [pkgRoot] :: InstalledPackageInfo -> Maybe FilePath
- Distribution.InstalledPackageInfo: [pkgUrl] :: InstalledPackageInfo_ m -> String
+ Distribution.InstalledPackageInfo: [pkgUrl] :: InstalledPackageInfo -> String
- Distribution.InstalledPackageInfo: [sourcePackageId] :: InstalledPackageInfo_ m -> PackageId
+ Distribution.InstalledPackageInfo: [sourcePackageId] :: InstalledPackageInfo -> PackageId
- Distribution.InstalledPackageInfo: [stability] :: InstalledPackageInfo_ m -> String
+ Distribution.InstalledPackageInfo: [stability] :: InstalledPackageInfo -> String
- Distribution.InstalledPackageInfo: [synopsis] :: InstalledPackageInfo_ m -> String
+ Distribution.InstalledPackageInfo: [synopsis] :: InstalledPackageInfo -> String
- Distribution.InstalledPackageInfo: [trusted] :: InstalledPackageInfo_ m -> Bool
+ Distribution.InstalledPackageInfo: [trusted] :: InstalledPackageInfo -> Bool
- Distribution.InstalledPackageInfo: emptyInstalledPackageInfo :: InstalledPackageInfo_ m
+ Distribution.InstalledPackageInfo: emptyInstalledPackageInfo :: InstalledPackageInfo
- Distribution.Package: class Package pkg => PackageInstalled pkg
+ Distribution.Package: class (HasUnitId pkg) => PackageInstalled pkg
- Distribution.Package: installedDepends :: PackageInstalled pkg => pkg -> [InstalledPackageId]
+ Distribution.Package: installedDepends :: PackageInstalled pkg => pkg -> [UnitId]
- Distribution.Package: installedPackageId :: PackageInstalled pkg => pkg -> InstalledPackageId
+ Distribution.Package: installedPackageId :: HasUnitId pkg => pkg -> UnitId
- Distribution.PackageDescription: BuildInfo :: Bool -> [Dependency] -> [String] -> [String] -> [String] -> [Dependency] -> [String] -> [FilePath] -> [FilePath] -> [FilePath] -> [ModuleName] -> Maybe Language -> [Language] -> [Extension] -> [Extension] -> [Extension] -> [String] -> [String] -> [String] -> [FilePath] -> [FilePath] -> [FilePath] -> [(CompilerFlavor, [String])] -> [(CompilerFlavor, [String])] -> [(CompilerFlavor, [String])] -> [(String, String)] -> [Dependency] -> Map PackageName ModuleRenaming -> BuildInfo
+ Distribution.PackageDescription: BuildInfo :: Bool -> [Dependency] -> [String] -> [String] -> [String] -> [Dependency] -> [String] -> [String] -> [FilePath] -> [FilePath] -> [FilePath] -> [ModuleName] -> Maybe Language -> [Language] -> [Extension] -> [Extension] -> [Extension] -> [String] -> [String] -> [String] -> [FilePath] -> [FilePath] -> [FilePath] -> [(CompilerFlavor, [String])] -> [(CompilerFlavor, [String])] -> [(CompilerFlavor, [String])] -> [(String, String)] -> [Dependency] -> Map PackageName ModuleRenaming -> BuildInfo
- Distribution.PackageDescription: PackageDescription :: PackageIdentifier -> License -> [FilePath] -> String -> String -> String -> String -> [(CompilerFlavor, VersionRange)] -> String -> String -> String -> [SourceRepo] -> String -> String -> String -> [(String, String)] -> [Dependency] -> Either Version VersionRange -> Maybe BuildType -> Maybe Library -> [Executable] -> [TestSuite] -> [Benchmark] -> [FilePath] -> FilePath -> [FilePath] -> [FilePath] -> [FilePath] -> PackageDescription
+ Distribution.PackageDescription: PackageDescription :: PackageIdentifier -> License -> [FilePath] -> String -> String -> String -> String -> [(CompilerFlavor, VersionRange)] -> String -> String -> String -> [SourceRepo] -> String -> String -> String -> [(String, String)] -> [Dependency] -> Either Version VersionRange -> Maybe BuildType -> Maybe SetupBuildInfo -> Maybe Library -> [Executable] -> [TestSuite] -> [Benchmark] -> [FilePath] -> FilePath -> [FilePath] -> [FilePath] -> [FilePath] -> PackageDescription
- Distribution.PackageDescription.Check: CheckPackageContentOps :: (FilePath -> m Bool) -> (FilePath -> m Bool) -> CheckPackageContentOps m
+ Distribution.PackageDescription.Check: CheckPackageContentOps :: (FilePath -> m Bool) -> (FilePath -> m Bool) -> (FilePath -> m [FilePath]) -> (FilePath -> m String) -> CheckPackageContentOps m
- Distribution.Simple.Build: startInterpreter :: Verbosity -> ProgramDb -> Compiler -> PackageDBStack -> IO ()
+ Distribution.Simple.Build: startInterpreter :: Verbosity -> ProgramDb -> Compiler -> Platform -> PackageDBStack -> IO ()
- Distribution.Simple.BuildPaths: mkLibName :: LibraryName -> String
+ Distribution.Simple.BuildPaths: mkLibName :: UnitId -> String
- Distribution.Simple.BuildPaths: mkProfLibName :: LibraryName -> String
+ Distribution.Simple.BuildPaths: mkProfLibName :: UnitId -> String
- Distribution.Simple.BuildPaths: mkSharedLibName :: CompilerId -> LibraryName -> String
+ Distribution.Simple.BuildPaths: mkSharedLibName :: CompilerId -> UnitId -> String
- Distribution.Simple.Command: noArg :: (Eq b, Monoid b) => b -> MkOptDescr (a -> b) (b -> a -> a) a
+ Distribution.Simple.Command: noArg :: (Eq b) => b -> MkOptDescr (a -> b) (b -> a -> a) a
- Distribution.Simple.GHC: getInstalledPackages :: Verbosity -> PackageDBStack -> ProgramConfiguration -> IO InstalledPackageIndex
+ Distribution.Simple.GHC: getInstalledPackages :: Verbosity -> Compiler -> PackageDBStack -> ProgramConfiguration -> IO InstalledPackageIndex
- Distribution.Simple.GHC: registerPackage :: Verbosity -> InstalledPackageInfo -> PackageDescription -> LocalBuildInfo -> Bool -> PackageDBStack -> IO ()
+ Distribution.Simple.GHC: registerPackage :: Verbosity -> ProgramConfiguration -> Bool -> PackageDBStack -> InstalledPackageInfo -> IO ()
- Distribution.Simple.GHC: startInterpreter :: Verbosity -> ProgramConfiguration -> Compiler -> PackageDBStack -> IO ()
+ Distribution.Simple.GHC: startInterpreter :: Verbosity -> ProgramConfiguration -> Compiler -> Platform -> PackageDBStack -> IO ()
- Distribution.Simple.GHCJS: registerPackage :: Verbosity -> InstalledPackageInfo -> PackageDescription -> LocalBuildInfo -> Bool -> PackageDBStack -> IO ()
+ Distribution.Simple.GHCJS: registerPackage :: Verbosity -> ProgramConfiguration -> Bool -> PackageDBStack -> InstalledPackageInfo -> IO ()
- Distribution.Simple.GHCJS: startInterpreter :: Verbosity -> ProgramConfiguration -> Compiler -> PackageDBStack -> IO ()
+ Distribution.Simple.GHCJS: startInterpreter :: Verbosity -> ProgramConfiguration -> Compiler -> Platform -> PackageDBStack -> IO ()
- Distribution.Simple.HaskellSuite: installLib :: Verbosity -> LocalBuildInfo -> FilePath -> FilePath -> FilePath -> PackageDescription -> Library -> IO ()
+ Distribution.Simple.HaskellSuite: installLib :: Verbosity -> LocalBuildInfo -> FilePath -> FilePath -> FilePath -> PackageDescription -> Library -> ComponentLocalBuildInfo -> IO ()
- Distribution.Simple.HaskellSuite: registerPackage :: Verbosity -> InstalledPackageInfo -> PackageDescription -> LocalBuildInfo -> Bool -> PackageDBStack -> IO ()
+ Distribution.Simple.HaskellSuite: registerPackage :: Verbosity -> ProgramConfiguration -> PackageDBStack -> InstalledPackageInfo -> IO ()
- Distribution.Simple.InstallDirs: absoluteInstallDirs :: PackageIdentifier -> PackageKey -> CompilerInfo -> CopyDest -> Platform -> InstallDirs PathTemplate -> InstallDirs FilePath
+ Distribution.Simple.InstallDirs: absoluteInstallDirs :: PackageIdentifier -> UnitId -> CompilerInfo -> CopyDest -> Platform -> InstallDirs PathTemplate -> InstallDirs FilePath
- Distribution.Simple.InstallDirs: initialPathTemplateEnv :: PackageIdentifier -> PackageKey -> CompilerInfo -> Platform -> PathTemplateEnv
+ Distribution.Simple.InstallDirs: initialPathTemplateEnv :: PackageIdentifier -> UnitId -> CompilerInfo -> Platform -> PathTemplateEnv
- Distribution.Simple.InstallDirs: packageTemplateEnv :: PackageIdentifier -> PackageKey -> PathTemplateEnv
+ Distribution.Simple.InstallDirs: packageTemplateEnv :: PackageIdentifier -> UnitId -> PathTemplateEnv
- Distribution.Simple.InstallDirs: prefixRelativeInstallDirs :: PackageIdentifier -> PackageKey -> CompilerInfo -> Platform -> InstallDirTemplates -> InstallDirs (Maybe FilePath)
+ Distribution.Simple.InstallDirs: prefixRelativeInstallDirs :: PackageIdentifier -> UnitId -> CompilerInfo -> Platform -> InstallDirTemplates -> InstallDirs (Maybe FilePath)
- Distribution.Simple.JHC: installLib :: Verbosity -> FilePath -> FilePath -> PackageDescription -> Library -> IO ()
+ Distribution.Simple.JHC: installLib :: Verbosity -> LocalBuildInfo -> FilePath -> FilePath -> FilePath -> PackageDescription -> Library -> ComponentLocalBuildInfo -> IO ()
- Distribution.Simple.LHC: registerPackage :: Verbosity -> InstalledPackageInfo -> PackageDescription -> LocalBuildInfo -> Bool -> PackageDBStack -> IO ()
+ Distribution.Simple.LHC: registerPackage :: Verbosity -> ProgramConfiguration -> PackageDBStack -> InstalledPackageInfo -> IO ()
- Distribution.Simple.LocalBuildInfo: BenchComponentLocalBuildInfo :: [(InstalledPackageId, PackageId)] -> Map PackageName ModuleRenaming -> ComponentLocalBuildInfo
+ Distribution.Simple.LocalBuildInfo: BenchComponentLocalBuildInfo :: [(UnitId, PackageId)] -> Map PackageName ModuleRenaming -> ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: ExeComponentLocalBuildInfo :: [(InstalledPackageId, PackageId)] -> Map PackageName ModuleRenaming -> ComponentLocalBuildInfo
+ Distribution.Simple.LocalBuildInfo: ExeComponentLocalBuildInfo :: [(UnitId, PackageId)] -> Map PackageName ModuleRenaming -> ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: LibComponentLocalBuildInfo :: [(InstalledPackageId, PackageId)] -> [ExposedModule] -> Map PackageName ModuleRenaming -> [LibraryName] -> ComponentLocalBuildInfo
+ Distribution.Simple.LocalBuildInfo: LibComponentLocalBuildInfo :: [(UnitId, PackageId)] -> UnitId -> String -> [ExposedModule] -> Map PackageName ModuleRenaming -> ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: LocalBuildInfo :: ConfigFlags -> [String] -> InstallDirTemplates -> Compiler -> Platform -> FilePath -> [(ComponentName, ComponentLocalBuildInfo, [ComponentName])] -> InstalledPackageIndex -> Maybe FilePath -> PackageDescription -> PackageKey -> [(ModuleName, (InstalledPackageInfo, ModuleName))] -> ProgramConfiguration -> PackageDBStack -> Bool -> Bool -> Bool -> Bool -> Bool -> OptimisationLevel -> DebugInfoLevel -> Bool -> Bool -> Bool -> Bool -> PathTemplate -> PathTemplate -> Bool -> LocalBuildInfo
+ Distribution.Simple.LocalBuildInfo: LocalBuildInfo :: ConfigFlags -> FlagAssignment -> [String] -> InstallDirTemplates -> Compiler -> Platform -> FilePath -> [(ComponentName, ComponentLocalBuildInfo, [ComponentName])] -> InstalledPackageIndex -> Maybe FilePath -> PackageDescription -> ProgramConfiguration -> PackageDBStack -> Bool -> Bool -> Bool -> Bool -> Bool -> ProfDetailLevel -> ProfDetailLevel -> OptimisationLevel -> DebugInfoLevel -> Bool -> Bool -> Bool -> Bool -> PathTemplate -> PathTemplate -> Bool -> LocalBuildInfo
- Distribution.Simple.LocalBuildInfo: TestComponentLocalBuildInfo :: [(InstalledPackageId, PackageId)] -> Map PackageName ModuleRenaming -> ComponentLocalBuildInfo
+ Distribution.Simple.LocalBuildInfo: TestComponentLocalBuildInfo :: [(UnitId, PackageId)] -> Map PackageName ModuleRenaming -> ComponentLocalBuildInfo
- Distribution.Simple.LocalBuildInfo: [componentPackageDeps] :: ComponentLocalBuildInfo -> [(InstalledPackageId, PackageId)]
+ Distribution.Simple.LocalBuildInfo: [componentPackageDeps] :: ComponentLocalBuildInfo -> [(UnitId, PackageId)]
- Distribution.Simple.LocalBuildInfo: externalPackageDeps :: LocalBuildInfo -> [(InstalledPackageId, PackageId)]
+ Distribution.Simple.LocalBuildInfo: externalPackageDeps :: LocalBuildInfo -> [(UnitId, PackageId)]
- Distribution.Simple.PackageIndex: allPackagesBySourcePackageId :: PackageInstalled a => PackageIndex a -> [(PackageId, [a])]
+ Distribution.Simple.PackageIndex: allPackagesBySourcePackageId :: HasUnitId a => PackageIndex a -> [(PackageId, [a])]
- Distribution.Simple.PackageIndex: brokenPackages :: PackageInstalled a => PackageIndex a -> [(a, [InstalledPackageId])]
+ Distribution.Simple.PackageIndex: brokenPackages :: PackageInstalled a => PackageIndex a -> [(a, [UnitId])]
- Distribution.Simple.PackageIndex: deleteInstalledPackageId :: PackageInstalled a => InstalledPackageId -> PackageIndex a -> PackageIndex a
+ Distribution.Simple.PackageIndex: deleteInstalledPackageId :: HasUnitId a => UnitId -> PackageIndex a -> PackageIndex a
- Distribution.Simple.PackageIndex: deletePackageName :: PackageInstalled a => PackageName -> PackageIndex a -> PackageIndex a
+ Distribution.Simple.PackageIndex: deletePackageName :: HasUnitId a => PackageName -> PackageIndex a -> PackageIndex a
- Distribution.Simple.PackageIndex: deleteSourcePackageId :: PackageInstalled a => PackageId -> PackageIndex a -> PackageIndex a
+ Distribution.Simple.PackageIndex: deleteSourcePackageId :: HasUnitId a => PackageId -> PackageIndex a -> PackageIndex a
- Distribution.Simple.PackageIndex: dependencyClosure :: PackageInstalled a => PackageIndex a -> [InstalledPackageId] -> Either (PackageIndex a) [(a, [InstalledPackageId])]
+ Distribution.Simple.PackageIndex: dependencyClosure :: PackageInstalled a => PackageIndex a -> [UnitId] -> Either (PackageIndex a) [(a, [UnitId])]
- Distribution.Simple.PackageIndex: dependencyGraph :: PackageInstalled a => PackageIndex a -> (Graph, Vertex -> a, InstalledPackageId -> Maybe Vertex)
+ Distribution.Simple.PackageIndex: dependencyGraph :: PackageInstalled a => PackageIndex a -> (Graph, Vertex -> a, UnitId -> Maybe Vertex)
- Distribution.Simple.PackageIndex: fromList :: PackageInstalled a => [a] -> PackageIndex a
+ Distribution.Simple.PackageIndex: fromList :: HasUnitId a => [a] -> PackageIndex a
- Distribution.Simple.PackageIndex: insert :: PackageInstalled a => a -> PackageIndex a -> PackageIndex a
+ Distribution.Simple.PackageIndex: insert :: HasUnitId a => a -> PackageIndex a -> PackageIndex a
- Distribution.Simple.PackageIndex: lookupDependency :: PackageInstalled a => PackageIndex a -> Dependency -> [(Version, [a])]
+ Distribution.Simple.PackageIndex: lookupDependency :: PackageIndex a -> Dependency -> [(Version, [a])]
- Distribution.Simple.PackageIndex: lookupInstalledPackageId :: PackageInstalled a => PackageIndex a -> InstalledPackageId -> Maybe a
+ Distribution.Simple.PackageIndex: lookupInstalledPackageId :: PackageIndex a -> UnitId -> Maybe a
- Distribution.Simple.PackageIndex: lookupPackageId :: PackageInstalled a => PackageIndex a -> PackageId -> Maybe a
+ Distribution.Simple.PackageIndex: lookupPackageId :: PackageIndex a -> PackageId -> Maybe a
- Distribution.Simple.PackageIndex: lookupPackageName :: PackageInstalled a => PackageIndex a -> PackageName -> [(Version, [a])]
+ Distribution.Simple.PackageIndex: lookupPackageName :: PackageIndex a -> PackageName -> [(Version, [a])]
- Distribution.Simple.PackageIndex: lookupSourcePackageId :: PackageInstalled a => PackageIndex a -> PackageId -> [a]
+ Distribution.Simple.PackageIndex: lookupSourcePackageId :: PackageIndex a -> PackageId -> [a]
- Distribution.Simple.PackageIndex: merge :: PackageInstalled a => PackageIndex a -> PackageIndex a -> PackageIndex a
+ Distribution.Simple.PackageIndex: merge :: HasUnitId a => PackageIndex a -> PackageIndex a -> PackageIndex a
- Distribution.Simple.PackageIndex: reverseDependencyClosure :: PackageInstalled a => PackageIndex a -> [InstalledPackageId] -> [a]
+ Distribution.Simple.PackageIndex: reverseDependencyClosure :: PackageInstalled a => PackageIndex a -> [UnitId] -> [a]
- Distribution.Simple.PackageIndex: searchByName :: PackageInstalled a => PackageIndex a -> String -> SearchResult [a]
+ Distribution.Simple.PackageIndex: searchByName :: PackageIndex a -> String -> SearchResult [a]
- Distribution.Simple.PackageIndex: searchByNameSubstring :: PackageInstalled a => PackageIndex a -> String -> [a]
+ Distribution.Simple.PackageIndex: searchByNameSubstring :: PackageIndex a -> String -> [a]
- Distribution.Simple.Program: ConfiguredProgram :: String -> Maybe Version -> [String] -> [String] -> [(String, Maybe String)] -> Map String String -> ProgramLocation -> ConfiguredProgram
+ Distribution.Simple.Program: ConfiguredProgram :: String -> Maybe Version -> [String] -> [String] -> [(String, Maybe String)] -> Map String String -> ProgramLocation -> [FilePath] -> ConfiguredProgram
- Distribution.Simple.Program: Program :: String -> (Verbosity -> ProgramSearchPath -> IO (Maybe FilePath)) -> (Verbosity -> FilePath -> IO (Maybe Version)) -> (Verbosity -> ConfiguredProgram -> IO ConfiguredProgram) -> Program
+ Distribution.Simple.Program: Program :: String -> (Verbosity -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath]))) -> (Verbosity -> FilePath -> IO (Maybe Version)) -> (Verbosity -> ConfiguredProgram -> IO ConfiguredProgram) -> Program
- Distribution.Simple.Program: [programFindLocation] :: Program -> Verbosity -> ProgramSearchPath -> IO (Maybe FilePath)
+ Distribution.Simple.Program: [programFindLocation] :: Program -> Verbosity -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath]))
- Distribution.Simple.Program.Find: findProgramOnSearchPath :: Verbosity -> ProgramSearchPath -> FilePath -> IO (Maybe FilePath)
+ Distribution.Simple.Program.Find: findProgramOnSearchPath :: Verbosity -> ProgramSearchPath -> FilePath -> IO (Maybe (FilePath, [FilePath]))
- Distribution.Simple.Program.GHC: GhcOptions :: Flag GhcMode -> NubListR String -> NubListR String -> NubListR FilePath -> NubListR ModuleName -> Flag FilePath -> Flag FilePath -> Flag Bool -> NubListR FilePath -> Flag PackageKey -> PackageDBStack -> NubListR (InstalledPackageId, PackageId, ModuleRenaming) -> Flag Bool -> Flag Bool -> [(ModuleName, (PackageKey, ModuleName))] -> NubListR FilePath -> NubListR FilePath -> NubListR String -> NubListR String -> Flag Bool -> Flag Bool -> NubListR String -> NubListR String -> NubListR FilePath -> NubListR FilePath -> NubListR FilePath -> Flag Language -> NubListR Extension -> Map Extension String -> Flag GhcOptimisation -> Flag Bool -> Flag Bool -> Flag Bool -> Flag (Maybe Int) -> Flag FilePath -> NubListR FilePath -> Flag String -> Flag String -> Flag String -> Flag String -> Flag FilePath -> Flag FilePath -> Flag FilePath -> Flag FilePath -> Flag GhcDynLinkMode -> Flag Bool -> Flag Bool -> Flag String -> NubListR FilePath -> Flag Verbosity -> Flag Bool -> GhcOptions
+ Distribution.Simple.Program.GHC: GhcOptions :: Flag GhcMode -> NubListR String -> NubListR String -> NubListR FilePath -> NubListR ModuleName -> Flag FilePath -> Flag FilePath -> Flag Bool -> NubListR FilePath -> Flag String -> PackageDBStack -> NubListR (UnitId, PackageId, ModuleRenaming) -> Flag Bool -> Flag Bool -> NubListR FilePath -> NubListR FilePath -> NubListR String -> NubListR String -> NubListR String -> Flag Bool -> Flag Bool -> NubListR String -> NubListR String -> NubListR FilePath -> NubListR FilePath -> NubListR FilePath -> Flag Language -> NubListR Extension -> Map Extension String -> Flag GhcOptimisation -> Flag Bool -> Flag Bool -> Flag GhcProfAuto -> Flag Bool -> Flag (Maybe Int) -> Flag FilePath -> NubListR FilePath -> Flag String -> Flag String -> Flag String -> Flag String -> Flag FilePath -> Flag FilePath -> Flag FilePath -> Flag FilePath -> Flag GhcDynLinkMode -> Flag Bool -> Flag Bool -> Flag String -> NubListR FilePath -> Flag Verbosity -> Flag Bool -> GhcOptions
- Distribution.Simple.Program.GHC: [ghcOptPackages] :: GhcOptions -> NubListR (InstalledPackageId, PackageId, ModuleRenaming)
+ Distribution.Simple.Program.GHC: [ghcOptPackages] :: GhcOptions -> NubListR (UnitId, PackageId, ModuleRenaming)
- Distribution.Simple.Program.GHC: ghcInvocation :: ConfiguredProgram -> Compiler -> GhcOptions -> ProgramInvocation
+ Distribution.Simple.Program.GHC: ghcInvocation :: ConfiguredProgram -> Compiler -> Platform -> GhcOptions -> ProgramInvocation
- Distribution.Simple.Program.GHC: renderGhcOptions :: Compiler -> GhcOptions -> [String]
+ Distribution.Simple.Program.GHC: renderGhcOptions :: Compiler -> Platform -> GhcOptions -> [String]
- Distribution.Simple.Program.GHC: runGHC :: Verbosity -> ConfiguredProgram -> Compiler -> GhcOptions -> IO ()
+ Distribution.Simple.Program.GHC: runGHC :: Verbosity -> ConfiguredProgram -> Compiler -> Platform -> GhcOptions -> IO ()
- Distribution.Simple.Program.HcPkg: HcPkgInfo :: ConfiguredProgram -> Bool -> Bool -> Bool -> Bool -> HcPkgInfo
+ Distribution.Simple.Program.HcPkg: HcPkgInfo :: ConfiguredProgram -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> HcPkgInfo
- Distribution.Simple.Program.HcPkg: init :: HcPkgInfo -> Verbosity -> FilePath -> IO ()
+ Distribution.Simple.Program.HcPkg: init :: HcPkgInfo -> Verbosity -> Bool -> FilePath -> IO ()
- Distribution.Simple.Program.Types: ConfiguredProgram :: String -> Maybe Version -> [String] -> [String] -> [(String, Maybe String)] -> Map String String -> ProgramLocation -> ConfiguredProgram
+ Distribution.Simple.Program.Types: ConfiguredProgram :: String -> Maybe Version -> [String] -> [String] -> [(String, Maybe String)] -> Map String String -> ProgramLocation -> [FilePath] -> ConfiguredProgram
- Distribution.Simple.Program.Types: Program :: String -> (Verbosity -> ProgramSearchPath -> IO (Maybe FilePath)) -> (Verbosity -> FilePath -> IO (Maybe Version)) -> (Verbosity -> ConfiguredProgram -> IO ConfiguredProgram) -> Program
+ Distribution.Simple.Program.Types: Program :: String -> (Verbosity -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath]))) -> (Verbosity -> FilePath -> IO (Maybe Version)) -> (Verbosity -> ConfiguredProgram -> IO ConfiguredProgram) -> Program
- Distribution.Simple.Program.Types: [programFindLocation] :: Program -> Verbosity -> ProgramSearchPath -> IO (Maybe FilePath)
+ Distribution.Simple.Program.Types: [programFindLocation] :: Program -> Verbosity -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath]))
- Distribution.Simple.Register: absoluteInstalledPackageInfo :: PackageDescription -> InstalledPackageId -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo -> InstalledPackageInfo
+ Distribution.Simple.Register: absoluteInstalledPackageInfo :: PackageDescription -> AbiHash -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo -> InstalledPackageInfo
- Distribution.Simple.Register: generalInstalledPackageInfo :: ([FilePath] -> [FilePath]) -> PackageDescription -> InstalledPackageId -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo -> InstallDirs FilePath -> InstalledPackageInfo
+ Distribution.Simple.Register: generalInstalledPackageInfo :: ([FilePath] -> [FilePath]) -> PackageDescription -> AbiHash -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo -> InstallDirs FilePath -> InstalledPackageInfo
- Distribution.Simple.Register: inplaceInstalledPackageInfo :: FilePath -> FilePath -> PackageDescription -> InstalledPackageId -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo -> InstalledPackageInfo
+ Distribution.Simple.Register: inplaceInstalledPackageInfo :: FilePath -> FilePath -> PackageDescription -> AbiHash -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo -> InstalledPackageInfo
- Distribution.Simple.Register: registerPackage :: Verbosity -> InstalledPackageInfo -> PackageDescription -> LocalBuildInfo -> Bool -> PackageDBStack -> IO ()
+ Distribution.Simple.Register: registerPackage :: Verbosity -> Compiler -> ProgramConfiguration -> Bool -> PackageDBStack -> InstalledPackageInfo -> IO ()
- Distribution.Simple.Setup: ConfigFlags :: ProgramConfiguration -> [(String, FilePath)] -> [(String, [String])] -> NubList FilePath -> Flag CompilerFlavor -> Flag FilePath -> Flag FilePath -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> [String] -> Flag OptimisationLevel -> Flag PathTemplate -> Flag PathTemplate -> InstallDirs (Flag PathTemplate) -> Flag FilePath -> [FilePath] -> [FilePath] -> Flag FilePath -> Flag Verbosity -> Flag Bool -> [Maybe PackageDB] -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> [Dependency] -> [(PackageName, InstalledPackageId)] -> [(ModuleName, (InstalledPackageId, ModuleName))] -> FlagAssignment -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag String -> Flag Bool -> Flag DebugInfoLevel -> ConfigFlags
+ Distribution.Simple.Setup: ConfigFlags :: Last' ProgramConfiguration -> [(String, FilePath)] -> [(String, [String])] -> NubList FilePath -> Flag CompilerFlavor -> Flag FilePath -> Flag FilePath -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag ProfDetailLevel -> Flag ProfDetailLevel -> [String] -> Flag OptimisationLevel -> Flag PathTemplate -> Flag PathTemplate -> InstallDirs (Flag PathTemplate) -> Flag FilePath -> [FilePath] -> [FilePath] -> [FilePath] -> Flag String -> Flag FilePath -> Flag Verbosity -> Flag Bool -> [Maybe PackageDB] -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> [Dependency] -> [(PackageName, UnitId)] -> FlagAssignment -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag String -> Flag Bool -> Flag DebugInfoLevel -> Maybe AllowNewer -> ConfigFlags
- Distribution.Simple.Setup: HaddockFlags :: [(String, FilePath)] -> [(String, [String])] -> Flag Bool -> Flag Bool -> Flag String -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag FilePath -> Flag Bool -> Flag FilePath -> Flag PathTemplate -> Flag FilePath -> Flag Bool -> Flag Verbosity -> HaddockFlags
+ Distribution.Simple.Setup: HaddockFlags :: [(String, FilePath)] -> [(String, [String])] -> Flag Bool -> Flag Bool -> Flag String -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag Bool -> Flag FilePath -> Flag Bool -> Flag FilePath -> Flag PathTemplate -> Flag FilePath -> Flag Bool -> Flag Verbosity -> HaddockFlags
- Distribution.Simple.Setup: [configDependencies] :: ConfigFlags -> [(PackageName, InstalledPackageId)]
+ Distribution.Simple.Setup: [configDependencies] :: ConfigFlags -> [(PackageName, UnitId)]
- Distribution.Simple.UHC: installLib :: Verbosity -> LocalBuildInfo -> FilePath -> FilePath -> FilePath -> PackageDescription -> Library -> IO ()
+ Distribution.Simple.UHC: installLib :: Verbosity -> LocalBuildInfo -> FilePath -> FilePath -> FilePath -> PackageDescription -> Library -> ComponentLocalBuildInfo -> IO ()
- Distribution.Simple.UHC: registerPackage :: Verbosity -> InstalledPackageInfo -> PackageDescription -> LocalBuildInfo -> Bool -> PackageDBStack -> IO ()
+ Distribution.Simple.UHC: registerPackage :: Verbosity -> Compiler -> ProgramConfiguration -> PackageDBStack -> InstalledPackageInfo -> IO ()
- Distribution.Simple.Utils: isInfixOf :: String -> String -> Bool
+ Distribution.Simple.Utils: isInfixOf :: Eq a => [a] -> [a] -> Bool
- Distribution.Simple.Utils: topHandlerWith :: (IOException -> IO a) -> IO a -> IO a
+ Distribution.Simple.Utils: topHandlerWith :: forall a. (SomeException -> IO a) -> IO a -> IO a
Files
- Cabal.cabal +107/−64
- Distribution/Compat/Binary.hs +9/−1
- Distribution/Compat/Binary/Class.hs +1/−13
- Distribution/Compat/CopyFile.hs +6/−9
- Distribution/Compat/Environment.hs +67/−2
- Distribution/Compat/GetShortPathName.hs +49/−0
- Distribution/Compat/Internal/TempFile.hs +124/−0
- Distribution/Compat/MonadFail.hs +36/−0
- Distribution/Compat/ReadP.hs +23/−19
- Distribution/Compat/Semigroup.hs +171/−0
- Distribution/Compat/TempFile.hs +0/−128
- Distribution/Compiler.hs +4/−4
- Distribution/InstalledPackageInfo.hs +50/−74
- Distribution/Lex.hs +55/−0
- Distribution/License.hs +4/−4
- Distribution/Make.hs +4/−7
- Distribution/ModuleName.hs +2/−3
- Distribution/Package.hs +66/−203
- Distribution/PackageDescription.hs +241/−109
- Distribution/PackageDescription/Check.hs +286/−139
- Distribution/PackageDescription/Configuration.hs +232/−82
- Distribution/PackageDescription/Parse.hs +96/−93
- Distribution/PackageDescription/PrettyPrint.hs +40/−31
- Distribution/ParseUtils.hs +11/−16
- Distribution/Simple.hs +166/−171
- Distribution/Simple/Bench.hs +11/−16
- Distribution/Simple/Build.hs +103/−102
- Distribution/Simple/Build/Macros.hs +15/−14
- Distribution/Simple/Build/PathsModule.hs +27/−13
- Distribution/Simple/BuildPaths.hs +14/−21
- Distribution/Simple/BuildTarget.hs +46/−45
- Distribution/Simple/CCompiler.hs +11/−13
- Distribution/Simple/Command.hs +39/−19
- Distribution/Simple/Compiler.hs +73/−6
- Distribution/Simple/Configure.hs +1775/−1429
- Distribution/Simple/GHC.hs +267/−149
- Distribution/Simple/GHC/IPI641.hs +0/−106
- Distribution/Simple/GHC/IPI642.hs +7/−47
- Distribution/Simple/GHC/IPIConvert.hs +50/−0
- Distribution/Simple/GHC/ImplInfo.hs +4/−3
- Distribution/Simple/GHC/Internal.hs +81/−45
- Distribution/Simple/GHCJS.hs +75/−101
- Distribution/Simple/Haddock.hs +71/−113
- Distribution/Simple/HaskellSuite.hs +9/−15
- Distribution/Simple/Install.hs +31/−30
- Distribution/Simple/InstallDirs.hs +32/−68
- Distribution/Simple/JHC.hs +14/−24
- Distribution/Simple/LHC.hs +29/−62
- Distribution/Simple/LocalBuildInfo.hs +52/−46
- Distribution/Simple/PackageIndex.hs +109/−181
- Distribution/Simple/PreProcess.hs +64/−32
- Distribution/Simple/Program.hs +8/−6
- Distribution/Simple/Program/Ar.hs +4/−7
- Distribution/Simple/Program/Builtin.hs +7/−32
- Distribution/Simple/Program/Db.hs +38/−34
- Distribution/Simple/Program/Find.hs +103/−44
- Distribution/Simple/Program/GHC.hs +104/−160
- Distribution/Simple/Program/HcPkg.hs +162/−77
- Distribution/Simple/Program/Hpc.hs +6/−7
- Distribution/Simple/Program/Internal.hs +46/−0
- Distribution/Simple/Program/Run.hs +1/−6
- Distribution/Simple/Program/Script.hs +0/−2
- Distribution/Simple/Program/Strip.hs +7/−9
- Distribution/Simple/Program/Types.hs +20/−9
- Distribution/Simple/Register.hs +97/−103
- Distribution/Simple/Setup.hs +267/−386
- Distribution/Simple/SrcDist.hs +25/−38
- Distribution/Simple/Test.hs +7/−13
- Distribution/Simple/Test/ExeV10.hs +25/−26
- Distribution/Simple/Test/LibV09.hs +30/−28
- Distribution/Simple/Test/Log.hs +10/−12
- Distribution/Simple/UHC.hs +40/−29
- Distribution/Simple/UserHooks.hs +4/−9
- Distribution/Simple/Utils.hs +188/−72
- Distribution/System.hs +38/−18
- Distribution/Text.hs +21/−16
- Distribution/Utils/NubList.hs +11/−9
- Distribution/Verbosity.hs +3/−2
- Distribution/Version.hs +116/−22
- Language/Haskell/Extension.hs +54/−2
- Setup.hs +3/−0
- changelog +28/−38
- doc/Cabal.css +49/−0
- doc/developing-packages.markdown +121/−51
- doc/index.markdown +1/−0
- doc/installing-packages.markdown +234/−13
- tests/PackageTests.hs +251/−140
- tests/PackageTests/AllowNewer/AllowNewer.cabal +25/−0
- tests/PackageTests/AllowNewer/benchmarks/Bench.hs +4/−0
- tests/PackageTests/AllowNewer/src/Foo.hs +4/−0
- tests/PackageTests/AllowNewer/tests/Test.hs +4/−0
- tests/PackageTests/BenchmarkExeV10/Check.hs +0/−16
- tests/PackageTests/BenchmarkOptions/Check.hs +0/−26
- tests/PackageTests/BenchmarkStanza/Check.hs +15/−37
- tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive1/Check.hs +0/−22
- tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive1/GlobalBuildDepsNotAdditive1.cabal +1/−1
- tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive1/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive2/Check.hs +0/−22
- tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive2/GlobalBuildDepsNotAdditive2.cabal +1/−1
- tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive2/lemon.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary0/Check.hs +0/−22
- tests/PackageTests/BuildDeps/InternalLibrary0/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary0/my.cabal +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary0/programs/lemon.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary1/Check.hs +0/−16
- tests/PackageTests/BuildDeps/InternalLibrary1/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary1/my.cabal +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary1/programs/lemon.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary2/Check.hs +0/−32
- tests/PackageTests/BuildDeps/InternalLibrary2/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary2/my.cabal +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary2/programs/lemon.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary2/to-install/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary2/to-install/my.cabal +1/−1
- tests/PackageTests/BuildDeps/InternalLibrary3/Check.hs +0/−32
- tests/PackageTests/BuildDeps/InternalLibrary3/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary3/my.cabal +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary3/programs/lemon.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary3/to-install/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary3/to-install/my.cabal +1/−1
- tests/PackageTests/BuildDeps/InternalLibrary4/Check.hs +0/−32
- tests/PackageTests/BuildDeps/InternalLibrary4/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary4/my.cabal +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary4/programs/lemon.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary4/to-install/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/InternalLibrary4/to-install/my.cabal +1/−1
- tests/PackageTests/BuildDeps/SameDepsAllRound/Check.hs +0/−21
- tests/PackageTests/BuildDeps/SameDepsAllRound/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/SameDepsAllRound/SameDepsAllRound.cabal +1/−1
- tests/PackageTests/BuildDeps/SameDepsAllRound/lemon.hs +2/−2
- tests/PackageTests/BuildDeps/SameDepsAllRound/pineapple.hs +2/−2
- tests/PackageTests/BuildDeps/TargetSpecificDeps1/Check.hs +0/−29
- tests/PackageTests/BuildDeps/TargetSpecificDeps1/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/TargetSpecificDeps1/lemon.hs +2/−2
- tests/PackageTests/BuildDeps/TargetSpecificDeps1/my.cabal +1/−1
- tests/PackageTests/BuildDeps/TargetSpecificDeps2/Check.hs +0/−21
- tests/PackageTests/BuildDeps/TargetSpecificDeps2/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/TargetSpecificDeps2/my.cabal +1/−1
- tests/PackageTests/BuildDeps/TargetSpecificDeps3/Check.hs +0/−28
- tests/PackageTests/BuildDeps/TargetSpecificDeps3/MyLibrary.hs +2/−2
- tests/PackageTests/BuildDeps/TargetSpecificDeps3/lemon.hs +2/−2
- tests/PackageTests/BuildDeps/TargetSpecificDeps3/my.cabal +1/−1
- tests/PackageTests/BuildTestSuiteDetailedV09/Check.hs +0/−18
- tests/PackageTests/BuildTestSuiteDetailedV09/Dummy.hs +0/−6
- tests/PackageTests/BuildTestSuiteDetailedV09/Dummy2.hs +6/−0
- tests/PackageTests/BuildTestSuiteDetailedV09/my.cabal +0/−19
- tests/PackageTests/BuildableField/BuildableField.cabal +16/−0
- tests/PackageTests/BuildableField/Main.hs +4/−0
- tests/PackageTests/CMain/Check.hs +0/−20
- tests/PackageTests/CMain/Setup.hs +0/−3
- tests/PackageTests/DeterministicAr/Check.hs +14/−70
- tests/PackageTests/DuplicateModuleName/DuplicateModuleName.cabal +25/−0
- tests/PackageTests/DuplicateModuleName/src/Foo.hs +12/−0
- tests/PackageTests/DuplicateModuleName/tests/Foo.hs +18/−0
- tests/PackageTests/DuplicateModuleName/tests2/Foo.hs +18/−0
- tests/PackageTests/EmptyLib/Check.hs +0/−16
- tests/PackageTests/GhcPkgGuess/SameDirectory/SameDirectory.cabal +11/−0
- tests/PackageTests/GhcPkgGuess/SameDirectory/ghc +6/−0
- tests/PackageTests/GhcPkgGuess/SameDirectory/ghc-pkg +3/−0
- tests/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/SameDirectory.cabal +11/−0
- tests/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/ghc-7.10 +6/−0
- tests/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/ghc-pkg-ghc-7.10 +3/−0
- tests/PackageTests/GhcPkgGuess/SameDirectoryVersion/SameDirectory.cabal +11/−0
- tests/PackageTests/GhcPkgGuess/SameDirectoryVersion/ghc-7.10 +6/−0
- tests/PackageTests/GhcPkgGuess/SameDirectoryVersion/ghc-pkg-7.10 +3/−0
- tests/PackageTests/GhcPkgGuess/Symlink/SameDirectory.cabal +11/−0
- tests/PackageTests/GhcPkgGuess/Symlink/bin/ghc +6/−0
- tests/PackageTests/GhcPkgGuess/Symlink/bin/ghc-pkg +3/−0
- tests/PackageTests/GhcPkgGuess/SymlinkGhcVersion/SameDirectory.cabal +11/−0
- tests/PackageTests/GhcPkgGuess/SymlinkGhcVersion/bin/ghc-7.10 +6/−0
- tests/PackageTests/GhcPkgGuess/SymlinkGhcVersion/bin/ghc-pkg-7.10 +3/−0
- tests/PackageTests/GhcPkgGuess/SymlinkVersion/SameDirectory.cabal +11/−0
- tests/PackageTests/GhcPkgGuess/SymlinkVersion/bin/ghc-7.10 +6/−0
- tests/PackageTests/GhcPkgGuess/SymlinkVersion/bin/ghc-pkg-ghc-7.10 +3/−0
- tests/PackageTests/Haddock/Check.hs +0/−42
- tests/PackageTests/HaddockNewline/A.hs +1/−0
- tests/PackageTests/HaddockNewline/HaddockNewline.cabal +20/−0
- tests/PackageTests/HaddockNewline/Setup.hs +2/−0
- tests/PackageTests/Options.hs +19/−0
- tests/PackageTests/OrderFlags/Check.hs +0/−24
- tests/PackageTests/PackageTester.hs +602/−217
- tests/PackageTests/PathsModule/Executable/Check.hs +0/−16
- tests/PackageTests/PathsModule/Library/Check.hs +0/−16
- tests/PackageTests/PreProcess/Check.hs +0/−16
- tests/PackageTests/PreProcessExtraSources/Foo.hsc +9/−0
- tests/PackageTests/PreProcessExtraSources/Main.hs +8/−0
- tests/PackageTests/PreProcessExtraSources/my.cabal +32/−0
- tests/PackageTests/ReexportedModules/Check.hs +0/−41
- tests/PackageTests/TemplateHaskell/Check.hs +0/−41
- tests/PackageTests/TestNameCollision/child/Child.hs +2/−0
- tests/PackageTests/TestNameCollision/child/child.cabal +19/−0
- tests/PackageTests/TestNameCollision/child/tests/Test.hs +13/−0
- tests/PackageTests/TestNameCollision/parent/Parent.hs +1/−0
- tests/PackageTests/TestNameCollision/parent/parent.cabal +13/−0
- tests/PackageTests/TestOptions/Check.hs +0/−26
- tests/PackageTests/TestStanza/Check.hs +14/−38
- tests/PackageTests/TestSuiteExeV10/Check.hs +0/−147
- tests/PackageTests/TestSuiteExeV10/Foo.hs +0/−4
- tests/PackageTests/TestSuiteExeV10/my.cabal +0/−15
- tests/PackageTests/TestSuiteExeV10/tests/test-Foo.hs +0/−8
- tests/PackageTests/TestSuiteTests/ExeV10/Check.hs +129/−0
- tests/PackageTests/TestSuiteTests/ExeV10/Foo.hs +4/−0
- tests/PackageTests/TestSuiteTests/ExeV10/my.cabal +21/−0
- tests/PackageTests/TestSuiteTests/ExeV10/tests/test-Foo.hs +12/−0
- tests/PackageTests/TestSuiteTests/ExeV10/tests/test-Short.hs +11/−0
- tests/PackageTests/TestSuiteTests/LibV09/Lib.hs +11/−0
- tests/PackageTests/TestSuiteTests/LibV09/LibV09.cabal +21/−0
- tests/PackageTests/TestSuiteTests/LibV09/tests/Deadlock.hs +8/−0
- tests/PackageTests/Tests.hs +307/−0
- tests/PackageTests/UniqueIPID/P1/M.hs +3/−0
- tests/PackageTests/UniqueIPID/P1/my.cabal +15/−0
- tests/PackageTests/UniqueIPID/P2/M.hs +3/−0
- tests/PackageTests/UniqueIPID/P2/my.cabal +15/−0
- tests/PackageTests/multInst/my.cabal +16/−0
- tests/README.md +19/−15
- tests/Test/Laws.hs +79/−0
- tests/Test/QuickCheck/Utils.hs +29/−0
- tests/UnitTests.hs +19/−12
- tests/UnitTests/Distribution/Compat/CreatePipe.hs +3/−4
- tests/UnitTests/Distribution/Compat/ReadP.hs +3/−3
- tests/UnitTests/Distribution/Simple/Program/Internal.hs +36/−0
- tests/UnitTests/Distribution/Simple/Utils.hs +59/−0
- tests/UnitTests/Distribution/System.hs +29/−0
- tests/UnitTests/Distribution/Utils/NubList.hs +4/−5
- tests/UnitTests/Distribution/Version.hs +711/−0
Cabal.cabal view
@@ -1,5 +1,5 @@ name: Cabal-version: 1.22.8.0+version: 1.24.0.0 copyright: 2003-2006, Isaac Jones 2005-2011, Duncan Coutts license: BSD3@@ -20,16 +20,22 @@ category: Distribution cabal-version: >=1.10 build-type: Simple--- Even though we do use the default Setup.lhs it's vital to bootstrapping--- that we build Setup.lhs using our own local Cabal source code.+-- If we use a new Cabal feature, this needs to be changed to Custom so+-- we can bootstrap. extra-source-files: README.md tests/README.md changelog- doc/developing-packages.markdown doc/index.markdown+ doc/Cabal.css doc/developing-packages.markdown doc/index.markdown doc/installing-packages.markdown doc/misc.markdown - -- Generated with 'misc/gen-extra-source-files.sh' & 'M-x sort-lines':+ -- Generated with 'misc/gen-extra-source-files.sh'+ -- Do NOT edit this section manually; instead, run the script.+ -- BEGIN gen-extra-source-files+ tests/PackageTests/AllowNewer/AllowNewer.cabal+ tests/PackageTests/AllowNewer/benchmarks/Bench.hs+ tests/PackageTests/AllowNewer/src/Foo.hs+ tests/PackageTests/AllowNewer/tests/Test.hs tests/PackageTests/BenchmarkExeV10/Foo.hs tests/PackageTests/BenchmarkExeV10/benchmarks/bench-Foo.hs tests/PackageTests/BenchmarkExeV10/my.cabal@@ -74,20 +80,46 @@ tests/PackageTests/BuildDeps/TargetSpecificDeps3/MyLibrary.hs tests/PackageTests/BuildDeps/TargetSpecificDeps3/lemon.hs tests/PackageTests/BuildDeps/TargetSpecificDeps3/my.cabal- tests/PackageTests/BuildTestSuiteDetailedV09/Dummy.hs- tests/PackageTests/BuildTestSuiteDetailedV09/my.cabal+ tests/PackageTests/BuildTestSuiteDetailedV09/Dummy2.hs+ tests/PackageTests/BuildableField/BuildableField.cabal+ tests/PackageTests/BuildableField/Main.hs tests/PackageTests/CMain/Bar.hs- tests/PackageTests/CMain/Setup.hs tests/PackageTests/CMain/foo.c tests/PackageTests/CMain/my.cabal tests/PackageTests/DeterministicAr/Lib.hs tests/PackageTests/DeterministicAr/my.cabal+ tests/PackageTests/DuplicateModuleName/DuplicateModuleName.cabal+ tests/PackageTests/DuplicateModuleName/src/Foo.hs+ tests/PackageTests/DuplicateModuleName/tests/Foo.hs+ tests/PackageTests/DuplicateModuleName/tests2/Foo.hs tests/PackageTests/EmptyLib/empty/empty.cabal+ tests/PackageTests/GhcPkgGuess/SameDirectory/SameDirectory.cabal+ tests/PackageTests/GhcPkgGuess/SameDirectory/ghc+ tests/PackageTests/GhcPkgGuess/SameDirectory/ghc-pkg+ tests/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/SameDirectory.cabal+ tests/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/ghc-7.10+ tests/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/ghc-pkg-ghc-7.10+ tests/PackageTests/GhcPkgGuess/SameDirectoryVersion/SameDirectory.cabal+ tests/PackageTests/GhcPkgGuess/SameDirectoryVersion/ghc-7.10+ tests/PackageTests/GhcPkgGuess/SameDirectoryVersion/ghc-pkg-7.10+ tests/PackageTests/GhcPkgGuess/Symlink/SameDirectory.cabal+ tests/PackageTests/GhcPkgGuess/Symlink/bin/ghc+ tests/PackageTests/GhcPkgGuess/Symlink/bin/ghc-pkg+ tests/PackageTests/GhcPkgGuess/SymlinkGhcVersion/SameDirectory.cabal+ tests/PackageTests/GhcPkgGuess/SymlinkGhcVersion/bin/ghc-7.10+ tests/PackageTests/GhcPkgGuess/SymlinkGhcVersion/bin/ghc-pkg-7.10+ tests/PackageTests/GhcPkgGuess/SymlinkVersion/SameDirectory.cabal+ tests/PackageTests/GhcPkgGuess/SymlinkVersion/bin/ghc-7.10+ tests/PackageTests/GhcPkgGuess/SymlinkVersion/bin/ghc-pkg-ghc-7.10 tests/PackageTests/Haddock/CPP.hs tests/PackageTests/Haddock/Literate.lhs tests/PackageTests/Haddock/NoCPP.hs tests/PackageTests/Haddock/Simple.hs tests/PackageTests/Haddock/my.cabal+ tests/PackageTests/HaddockNewline/A.hs+ tests/PackageTests/HaddockNewline/HaddockNewline.cabal+ tests/PackageTests/HaddockNewline/Setup.hs+ tests/PackageTests/Options.hs tests/PackageTests/OrderFlags/Foo.hs tests/PackageTests/OrderFlags/my.cabal tests/PackageTests/PathsModule/Executable/Main.hs@@ -96,6 +128,9 @@ tests/PackageTests/PreProcess/Foo.hsc tests/PackageTests/PreProcess/Main.hs tests/PackageTests/PreProcess/my.cabal+ tests/PackageTests/PreProcessExtraSources/Foo.hsc+ tests/PackageTests/PreProcessExtraSources/Main.hs+ tests/PackageTests/PreProcessExtraSources/my.cabal tests/PackageTests/ReexportedModules/ReexportedModules.cabal tests/PackageTests/TemplateHaskell/dynamic/Exe.hs tests/PackageTests/TemplateHaskell/dynamic/Lib.hs@@ -109,17 +144,33 @@ tests/PackageTests/TemplateHaskell/vanilla/Lib.hs tests/PackageTests/TemplateHaskell/vanilla/TH.hs tests/PackageTests/TemplateHaskell/vanilla/my.cabal+ tests/PackageTests/TestNameCollision/child/Child.hs+ tests/PackageTests/TestNameCollision/child/child.cabal+ tests/PackageTests/TestNameCollision/child/tests/Test.hs+ tests/PackageTests/TestNameCollision/parent/Parent.hs+ tests/PackageTests/TestNameCollision/parent/parent.cabal tests/PackageTests/TestOptions/TestOptions.cabal tests/PackageTests/TestOptions/test-TestOptions.hs tests/PackageTests/TestStanza/my.cabal- tests/PackageTests/TestSuiteExeV10/Foo.hs- tests/PackageTests/TestSuiteExeV10/my.cabal- tests/PackageTests/TestSuiteExeV10/tests/test-Foo.hs+ tests/PackageTests/TestSuiteTests/ExeV10/Foo.hs+ tests/PackageTests/TestSuiteTests/ExeV10/my.cabal+ tests/PackageTests/TestSuiteTests/ExeV10/tests/test-Foo.hs+ tests/PackageTests/TestSuiteTests/ExeV10/tests/test-Short.hs+ tests/PackageTests/TestSuiteTests/LibV09/Lib.hs+ tests/PackageTests/TestSuiteTests/LibV09/LibV09.cabal+ tests/PackageTests/TestSuiteTests/LibV09/tests/Deadlock.hs+ tests/PackageTests/Tests.hs+ tests/PackageTests/UniqueIPID/P1/M.hs+ tests/PackageTests/UniqueIPID/P1/my.cabal+ tests/PackageTests/UniqueIPID/P2/M.hs+ tests/PackageTests/UniqueIPID/P2/my.cabal+ tests/PackageTests/multInst/my.cabal tests/Setup.hs tests/hackage/check.sh tests/hackage/download.sh tests/hackage/unpack.sh tests/misc/ghc-supported-languages.hs+ -- END gen-extra-source-files source-repository head type: git@@ -131,16 +182,16 @@ library build-depends:- base >= 4.4 && < 5,- deepseq >= 1.3 && < 1.5,- filepath >= 1 && < 1.5,- directory >= 1 && < 1.3,- process >= 1.1.0.1 && < 1.3,- time >= 1.1 && < 1.6,- containers >= 0.1 && < 0.6, array >= 0.1 && < 0.6,- pretty >= 1 && < 1.2,- bytestring >= 0.9+ base >= 4.5 && < 5,+ bytestring >= 0.9 && < 1,+ containers >= 0.4 && < 0.6,+ deepseq >= 1.3 && < 1.5,+ directory >= 1.1 && < 1.3,+ filepath >= 1.3 && < 1.5,+ pretty >= 1.1 && < 1.2,+ process >= 1.1.0.1 && < 1.5,+ time >= 1.4 && < 1.7 if flag(bundled-binary-generic) build-depends: binary >= 0.5 && < 0.7@@ -153,15 +204,24 @@ if !os(windows) build-depends:- unix >= 2.0 && < 2.8+ unix >= 2.5 && < 2.8 + if os(windows)+ build-depends:+ Win32 >= 2.2 && < 2.4+ ghc-options: -Wall -fno-ignore-asserts -fwarn-tabs+ if impl(ghc >= 8.0)+ ghc-options: -Wcompat -Wnoncanonical-monad-instances+ -Wnoncanonical-monadfail-instances exposed-modules: Distribution.Compat.CreatePipe Distribution.Compat.Environment Distribution.Compat.Exception+ Distribution.Compat.Internal.TempFile Distribution.Compat.ReadP+ Distribution.Compat.Semigroup Distribution.Compiler Distribution.InstalledPackageInfo Distribution.License@@ -208,6 +268,7 @@ Distribution.Simple.Program.GHC Distribution.Simple.Program.HcPkg Distribution.Simple.Program.Hpc+ Distribution.Simple.Program.Internal Distribution.Simple.Program.Ld Distribution.Simple.Program.Run Distribution.Simple.Program.Script@@ -230,15 +291,17 @@ Distribution.Verbosity Distribution.Version Language.Haskell.Extension+ Distribution.Compat.Binary other-modules:- Distribution.Compat.Binary Distribution.Compat.CopyFile- Distribution.Compat.TempFile+ Distribution.Compat.GetShortPathName+ Distribution.Compat.MonadFail Distribution.GetOpt+ Distribution.Lex Distribution.Simple.GHC.Internal- Distribution.Simple.GHC.IPI641 Distribution.Simple.GHC.IPI642+ Distribution.Simple.GHC.IPIConvert Distribution.Simple.GHC.ImplInfo Paths_Cabal @@ -248,24 +311,30 @@ Distribution.Compat.Binary.Generic default-language: Haskell98- default-extensions: CPP -- Small, fast running tests. test-suite unit-tests type: exitcode-stdio-1.0 hs-source-dirs: tests other-modules:+ Test.Laws+ Test.QuickCheck.Utils UnitTests.Distribution.Compat.CreatePipe UnitTests.Distribution.Compat.ReadP+ UnitTests.Distribution.Simple.Program.Internal+ UnitTests.Distribution.Simple.Utils+ UnitTests.Distribution.System UnitTests.Distribution.Utils.NubList+ UnitTests.Distribution.Version main-is: UnitTests.hs build-depends: base,- test-framework,- test-framework-hunit,- test-framework-quickcheck2,- HUnit,- QuickCheck < 2.9,+ directory,+ tasty,+ tasty-hunit,+ tasty-quickcheck,+ pretty,+ QuickCheck >= 2.7 && < 2.9, Cabal ghc-options: -Wall default-language: Haskell98@@ -275,54 +344,28 @@ type: exitcode-stdio-1.0 main-is: PackageTests.hs other-modules:- PackageTests.BenchmarkExeV10.Check- PackageTests.BenchmarkOptions.Check PackageTests.BenchmarkStanza.Check- PackageTests.BuildDeps.GlobalBuildDepsNotAdditive1.Check- PackageTests.BuildDeps.GlobalBuildDepsNotAdditive2.Check- PackageTests.BuildDeps.InternalLibrary0.Check- PackageTests.BuildDeps.InternalLibrary1.Check- PackageTests.BuildDeps.InternalLibrary2.Check- PackageTests.BuildDeps.InternalLibrary3.Check- PackageTests.BuildDeps.InternalLibrary4.Check- PackageTests.BuildDeps.SameDepsAllRound.Check- PackageTests.BuildDeps.TargetSpecificDeps1.Check- PackageTests.BuildDeps.TargetSpecificDeps2.Check- PackageTests.BuildDeps.TargetSpecificDeps3.Check- PackageTests.BuildTestSuiteDetailedV09.Check- PackageTests.CMain.Check+ PackageTests.TestStanza.Check PackageTests.DeterministicAr.Check- PackageTests.EmptyLib.Check- PackageTests.Haddock.Check- PackageTests.OrderFlags.Check+ PackageTests.TestSuiteTests.ExeV10.Check PackageTests.PackageTester- PackageTests.PathsModule.Executable.Check- PackageTests.PathsModule.Library.Check- PackageTests.PreProcess.Check- PackageTests.ReexportedModules.Check- PackageTests.TemplateHaskell.Check- PackageTests.TestOptions.Check- PackageTests.TestStanza.Check- PackageTests.TestSuiteExeV10.Check hs-source-dirs: tests build-depends: base, containers,- test-framework,- test-framework-quickcheck2 >= 0.2.12,- test-framework-hunit,- HUnit,- QuickCheck >= 2.1.0.1 && < 2.9,+ tagged,+ tasty,+ tasty-hunit,+ transformers, Cabal, process, directory, filepath,- extensible-exceptions, bytestring, regex-posix, old-time if !os(windows)- build-depends: unix- ghc-options: -Wall+ build-depends: unix, exceptions+ ghc-options: -Wall -rtsopts default-extensions: CPP default-language: Haskell98
Distribution/Compat/Binary.hs view
@@ -1,4 +1,7 @@ {-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ >= 711+{-# LANGUAGE PatternSynonyms #-}+#endif #ifndef MIN_VERSION_binary #define MIN_VERSION_binary(x, y, z) 0@@ -14,7 +17,12 @@ #endif ) where -import Control.Exception (ErrorCall(..), catch, evaluate)+import Control.Exception (catch, evaluate)+#if __GLASGOW_HASKELL__ >= 711+import Control.Exception (pattern ErrorCall)+#else+import Control.Exception (ErrorCall(..))+#endif import Data.ByteString.Lazy (ByteString) #if __GLASGOW_HASKELL__ < 706
Distribution/Compat/Binary/Class.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, FlexibleContexts #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE Trustworthy #-} {-# LANGUAGE DefaultSignatures #-} -----------------------------------------------------------------------------@@ -53,13 +53,8 @@ import GHC.Generics ------ This isn't available in older Hugs or older GHC----#if __GLASGOW_HASKELL__ >= 606 import qualified Data.Sequence as Seq import qualified Data.Foldable as Fold-#endif ------------------------------------------------------------------------ @@ -467,11 +462,6 @@ ------------------------------------------------------------------------ -- Queues and Sequences -#if __GLASGOW_HASKELL__ >= 606------ This is valid Hugs, but you need the most recent Hugs---- instance (Binary e) => Binary (Seq.Seq e) where put s = put (Seq.length s) >> Fold.mapM_ put s get = do n <- get :: Get Int@@ -480,8 +470,6 @@ rep xs n g = xs `seq` n `seq` do x <- g rep (xs Seq.|> x) (n-1) g--#endif ------------------------------------------------------------------------ -- Floating point
Distribution/Compat/CopyFile.hs view
@@ -11,24 +11,22 @@ setDirOrdinary, ) where +import Distribution.Compat.Exception+import Distribution.Compat.Internal.TempFile import Control.Monad ( when, unless ) import Control.Exception- ( bracket, bracketOnError, throwIO )+ ( bracketOnError, throwIO ) import qualified Data.ByteString.Lazy as BSL-import Distribution.Compat.Exception- ( catchIO ) import System.IO.Error ( ioeSetLocation ) import System.Directory ( doesFileExist, renameFile, removeFile )-import Distribution.Compat.TempFile- ( openBinaryTempFile ) import System.FilePath ( takeDirectory ) import System.IO- ( openBinaryFile, IOMode(ReadMode), hClose, hGetBuf, hPutBuf+ ( IOMode(ReadMode), hClose, hGetBuf, hPutBuf , withBinaryFile ) import Foreign ( allocaBytes )@@ -69,7 +67,7 @@ copyFile fromFPath toFPath = copy `catchIO` (\ioe -> throwIO (ioeSetLocation ioe "copyFile"))- where copy = bracket (openBinaryFile fromFPath ReadMode) hClose $ \hFrom ->+ where copy = withBinaryFile fromFPath ReadMode $ \hFrom -> bracketOnError openTmp cleanTmp $ \(tmpFPath, hTmp) -> do allocaBytes bufferSize $ copyContents hFrom hTmp hClose hTmp@@ -100,8 +98,7 @@ filesEqual f1 f2 = do ex1 <- doesFileExist f1 ex2 <- doesFileExist f2- if not (ex1 && ex2) then return False else do-+ if not (ex1 && ex2) then return False else withBinaryFile f1 ReadMode $ \h1 -> withBinaryFile f2 ReadMode $ \h2 -> do c1 <- BSL.hGetContents h1
Distribution/Compat/Environment.hs view
@@ -1,14 +1,29 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-} {-# OPTIONS_HADDOCK hide #-} -module Distribution.Compat.Environment (getEnvironment)+module Distribution.Compat.Environment+ ( getEnvironment, lookupEnv, setEnv ) where import qualified System.Environment as System+#if __GLASGOW_HASKELL__ >= 706+import System.Environment (lookupEnv)+#else+import Distribution.Compat.Exception (catchIO)+#endif #ifdef mingw32_HOST_OS+import Control.Monad import qualified Data.Char as Char (toUpper)-#endif+import Foreign.C+import GHC.Windows+#else+import Foreign.C.Types+import Foreign.C.String+import Foreign.C.Error (throwErrnoIfMinus1_)+import System.Posix.Internals ( withFilePath )+#endif /* mingw32_HOST_OS */ getEnvironment :: IO [(String, String)] #ifdef mingw32_HOST_OS@@ -22,3 +37,53 @@ #else getEnvironment = System.getEnvironment #endif++#if __GLASGOW_HASKELL__ < 706+-- | @lookupEnv var@ returns the value of the environment variable @var@, or+-- @Nothing@ if there is no such value.+lookupEnv :: String -> IO (Maybe String)+lookupEnv name = (Just `fmap` System.getEnv name) `catchIO` const (return Nothing)+#endif /* __GLASGOW_HASKELL__ < 706 */++-- | @setEnv name value@ sets the specified environment variable to @value@.+--+-- Throws `Control.Exception.IOException` if either @name@ or @value@ is the+-- empty string or contains an equals sign.+setEnv :: String -> String -> IO ()+setEnv key value_+ | null value = error "Distribuiton.Compat.setEnv: empty string"+ | otherwise = setEnv_ key value+ where+ -- NOTE: Anything that follows NUL is ignored on both POSIX and Windows. We+ -- still strip it manually so that the null check above succeeds if a value+ -- starts with NUL.+ value = takeWhile (/= '\NUL') value_++setEnv_ :: String -> String -> IO ()++#ifdef mingw32_HOST_OS++setEnv_ key value = withCWString key $ \k -> withCWString value $ \v -> do+ success <- c_SetEnvironmentVariable k v+ unless success (throwGetLastError "setEnv")++# if defined(i386_HOST_ARCH)+# define WINDOWS_CCONV stdcall+# elif defined(x86_64_HOST_ARCH)+# define WINDOWS_CCONV ccall+# else+# error Unknown mingw32 arch+# endif /* i386_HOST_ARCH */++foreign import WINDOWS_CCONV unsafe "windows.h SetEnvironmentVariableW"+ c_SetEnvironmentVariable :: LPTSTR -> LPTSTR -> IO Bool+#else+setEnv_ key value = do+ withFilePath key $ \ keyP ->+ withFilePath value $ \ valueP ->+ throwErrnoIfMinus1_ "setenv" $+ c_setenv keyP valueP (fromIntegral (fromEnum True))++foreign import ccall unsafe "setenv"+ c_setenv :: CString -> CString -> CInt -> IO CInt+#endif /* mingw32_HOST_OS */
+ Distribution/Compat/GetShortPathName.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE CPP, ForeignFunctionInterface #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Compat.GetShortPathName+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : Windows-only+--+-- Win32 API 'GetShortPathName' function.++module Distribution.Compat.GetShortPathName ( getShortPathName )+ where++#ifdef mingw32_HOST_OS+import Control.Monad (void)++import qualified System.Win32 as Win32+import System.Win32 (LPCTSTR, LPTSTR, DWORD)+import Foreign.Marshal.Array (allocaArray)++#ifdef x86_64_HOST_ARCH+#define WINAPI ccall+#else+#define WINAPI stdcall+#endif++foreign import WINAPI unsafe "windows.h GetShortPathNameW"+ c_GetShortPathName :: LPCTSTR -> LPTSTR -> DWORD -> IO DWORD++-- | On Windows, retrieves the short path form of the specified path. On+-- non-Windows, does nothing. See https://github.com/haskell/cabal/issues/3185.+getShortPathName :: FilePath -> IO FilePath+getShortPathName path =+ Win32.withTString path $ \c_path ->+ allocaArray arr_len $ \c_out -> do+ void $ Win32.failIfZero "GetShortPathName failed!" $+ c_GetShortPathName c_path c_out c_len+ Win32.peekTString c_out+ where+ arr_len = length path + 1+ c_len = fromIntegral arr_len++#else++getShortPathName :: FilePath -> IO FilePath+getShortPathName path = return path++#endif
+ Distribution/Compat/Internal/TempFile.hs view
@@ -0,0 +1,124 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_HADDOCK hide #-}+module Distribution.Compat.Internal.TempFile (+ openTempFile,+ openBinaryTempFile,+ openNewBinaryFile,+ createTempDirectory,+ ) where++import Distribution.Compat.Exception++import System.FilePath ((</>))+import Foreign.C (CInt, eEXIST, getErrno, errnoToIOError)++import System.IO (Handle, openTempFile, openBinaryTempFile)+import Data.Bits ((.|.))+import System.Posix.Internals (c_open, c_close, o_CREAT, o_EXCL, o_RDWR,+ o_BINARY, o_NONBLOCK, o_NOCTTY,+ withFilePath, c_getpid)+import System.IO.Error (isAlreadyExistsError)+import GHC.IO.Handle.FD (fdToHandle)+import Control.Exception (onException)++#if defined(mingw32_HOST_OS) || defined(ghcjs_HOST_OS)+import System.Directory ( createDirectory )+#else+import qualified System.Posix+#endif++-- ------------------------------------------------------------+-- * temporary files+-- ------------------------------------------------------------++-- This is here for Haskell implementations that do not come with+-- System.IO.openTempFile. This includes nhc-1.20, hugs-2006.9.+-- TODO: Not sure about JHC+-- TODO: This file should probably be removed.++-- This is a copy/paste of the openBinaryTempFile definition, but+-- if uses 666 rather than 600 for the permissions. The base library+-- needs to be changed to make this better.+openNewBinaryFile :: FilePath -> String -> IO (FilePath, Handle)+openNewBinaryFile dir template = do+ pid <- c_getpid+ findTempName pid+ where+ -- We split off the last extension, so we can use .foo.ext files+ -- for temporary files (hidden on Unix OSes). Unfortunately we're+ -- below file path in the hierarchy here.+ (prefix,suffix) =+ case break (== '.') $ reverse template of+ -- First case: template contains no '.'s. Just re-reverse it.+ (rev_suffix, "") -> (reverse rev_suffix, "")+ -- Second case: template contains at least one '.'. Strip the+ -- dot from the prefix and prepend it to the suffix (if we don't+ -- do this, the unique number will get added after the '.' and+ -- thus be part of the extension, which is wrong.)+ (rev_suffix, '.':rest) -> (reverse rest, '.':reverse rev_suffix)+ -- Otherwise, something is wrong, because (break (== '.')) should+ -- always return a pair with either the empty string or a string+ -- beginning with '.' as the second component.+ _ -> error "bug in System.IO.openTempFile"++ oflags = rw_flags .|. o_EXCL .|. o_BINARY++ findTempName x = do+ fd <- withFilePath filepath $ \ f ->+ c_open f oflags 0o666+ if fd < 0+ then do+ errno <- getErrno+ if errno == eEXIST+ then findTempName (x+1)+ else ioError (errnoToIOError "openNewBinaryFile" errno Nothing (Just dir))+ else do+ -- TODO: We want to tell fdToHandle what the file path is,+ -- as any exceptions etc will only be able to report the+ -- FD currently+ h <- fdToHandle fd `onException` c_close fd+ return (filepath, h)+ where+ filename = prefix ++ show x ++ suffix+ filepath = dir `combine` filename++ -- FIXME: bits copied from System.FilePath+ combine a b+ | null b = a+ | null a = b+ | last a == pathSeparator = a ++ b+ | otherwise = a ++ [pathSeparator] ++ b++-- FIXME: Should use System.FilePath library+pathSeparator :: Char+#ifdef mingw32_HOST_OS+pathSeparator = '\\'+#else+pathSeparator = '/'+#endif++-- FIXME: Copied from GHC.Handle+std_flags, output_flags, rw_flags :: CInt+std_flags = o_NONBLOCK .|. o_NOCTTY+output_flags = std_flags .|. o_CREAT+rw_flags = output_flags .|. o_RDWR++createTempDirectory :: FilePath -> String -> IO FilePath+createTempDirectory dir template = do+ pid <- c_getpid+ findTempName pid+ where+ findTempName x = do+ let dirpath = dir </> template ++ "-" ++ show x+ r <- tryIO $ mkPrivateDir dirpath+ case r of+ Right _ -> return dirpath+ Left e | isAlreadyExistsError e -> findTempName (x+1)+ | otherwise -> ioError e++mkPrivateDir :: String -> IO ()+#if defined(mingw32_HOST_OS) || defined(ghcjs_HOST_OS)+mkPrivateDir s = createDirectory s+#else+mkPrivateDir s = System.Posix.createDirectory s 0o700+#endif
+ Distribution/Compat/MonadFail.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE CPP #-}++-- | Compatibility layer for "Control.Monad.Fail"+module Distribution.Compat.MonadFail ( MonadFail(fail) ) where+#if __GLASGOW_HASKELL__ >= 800+-- provided by base-4.9.0.0 and later+import Control.Monad.Fail (MonadFail(fail))+#else+-- the following code corresponds to+-- http://hackage.haskell.org/package/fail-4.9.0.0+import qualified Prelude as P+import Prelude hiding (fail)++import Text.ParserCombinators.ReadP+import Text.ParserCombinators.ReadPrec++class Monad m => MonadFail m where+ fail :: String -> m a++-- instances provided by base-4.9++instance MonadFail Maybe where+ fail _ = Nothing++instance MonadFail [] where+ fail _ = []++instance MonadFail IO where+ fail = P.fail++instance MonadFail ReadPrec where+ fail = P.fail -- = P (\_ -> fail s)++instance MonadFail ReadP where+ fail = P.fail+#endif
Distribution/Compat/ReadP.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Compat.ReadP@@ -70,12 +69,11 @@ ) where -import Control.Monad( MonadPlus(..), liftM, liftM2, ap )+import qualified Distribution.Compat.MonadFail as Fail++import Control.Monad( MonadPlus(..), liftM, liftM2, replicateM, ap, (>=>) ) import Data.Char (isSpace)-#if __GLASGOW_HASKELL__ < 710-import Control.Applicative (Applicative(..))-#endif-import Control.Applicative (Alternative(empty, (<|>)))+import Control.Applicative as AP (Applicative(..), Alternative(empty, (<|>))) infixr 5 +++, <++ @@ -96,18 +94,21 @@ fmap = liftM instance Applicative (P s) where- pure = return+ pure x = Result x Fail (<*>) = ap instance Monad (P s) where- return x = Result x Fail+ return = AP.pure - (Get f) >>= k = Get (\c -> f c >>= k)- (Look f) >>= k = Look (\s -> f s >>= k)+ (Get f) >>= k = Get (f >=> k)+ (Look f) >>= k = Look (f >=> k) Fail >>= _ = Fail (Result x p) >>= k = k x `mplus` (p >>= k) (Final r) >>= k = final [ys' | (x,s) <- r, ys' <- run (k x) s] + fail = Fail.fail++instance Fail.MonadFail (P s) where fail _ = Fail instance Alternative (P s) where@@ -155,14 +156,17 @@ fmap h (R f) = R (\k -> f (k . h)) instance Applicative (Parser r s) where- pure = return+ pure x = R (\k -> k x) (<*>) = ap instance Monad (Parser r s) where- return x = R (\k -> k x)- fail _ = R (\_ -> Fail)+ return = AP.pure+ fail = Fail.fail R m >>= f = R (\k -> m (\a -> let R m' = f a in m' k)) +instance Fail.MonadFail (Parser r s) where+ fail _ = R (const Fail)+ --instance MonadPlus (Parser r s) where -- mzero = pfail -- mplus = (+++)@@ -197,7 +201,7 @@ pfail :: ReadP r a -- ^ Always fails.-pfail = R (\_ -> Fail)+pfail = R (const Fail) (+++) :: ReadP r a -> ReadP r a -> ReadP r a -- ^ Symmetric choice.@@ -230,7 +234,7 @@ where gath l (Get f) = Get (\c -> gath (l.(c:)) (f c)) gath _ Fail = Fail- gath l (Look f) = Look (\s -> gath l (f s))+ gath l (Look f) = Look (gath l . f) gath l (Result k p) = k (l []) `mplus` gath l p gath _ (Final _) = error "do not use readS_to_P in gather!" @@ -250,9 +254,9 @@ -- ^ Parses and returns the specified string. string this = do s <- look; scan this s where- scan [] _ = do return this- scan (x:xs) (y:ys) | x == y = do get >> scan xs ys- scan _ _ = do pfail+ scan [] _ = return this+ scan (x:xs) (y:ys) | x == y = get >> scan xs ys+ scan _ _ = pfail munch :: (Char -> Bool) -> ReadP r String -- ^ Parses the first zero or more characters satisfying the predicate.@@ -288,7 +292,7 @@ count :: Int -> ReadP r a -> ReadP r [a] -- ^ @ count n p @ parses @n@ occurrences of @p@ in sequence. A list of -- results is returned.-count n p = sequence (replicate n p)+count n p = replicateM n p between :: ReadP r open -> ReadP r close -> ReadP r a -> ReadP r a -- ^ @ between open close p @ parses @open@, followed by @p@ and finally
+ Distribution/Compat/Semigroup.hs view
@@ -0,0 +1,171 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeOperators #-}++-- | Compatibility layer for "Data.Semigroup"+module Distribution.Compat.Semigroup+ ( Semigroup((<>))+ , Mon.Monoid(..)+ , All(..)+ , Any(..)++ , Last'(..)++ , gmappend+ , gmempty+ ) where++import Distribution.Compat.Binary (Binary)++import Control.Applicative as App+import GHC.Generics+#if __GLASGOW_HASKELL__ >= 711+-- Data.Semigroup is available since GHC 8.0/base-4.9+import Data.Semigroup+import qualified Data.Monoid as Mon+#else+-- provide internal simplified non-exposed class for older GHCs+import Data.Monoid as Mon (Monoid(..), All(..), Any(..), Dual(..))+-- containers+import Data.Set (Set)+import Data.IntSet (IntSet)+import Data.Map (Map)+import Data.IntMap (IntMap)+++class Semigroup a where+ (<>) :: a -> a -> a++-- several primitive instances+instance Semigroup () where+ _ <> _ = ()++instance Semigroup [a] where+ (<>) = (++)++instance Semigroup a => Semigroup (Dual a) where+ Dual a <> Dual b = Dual (b <> a)++instance Semigroup a => Semigroup (Maybe a) where+ Nothing <> b = b+ a <> Nothing = a+ Just a <> Just b = Just (a <> b)++instance Semigroup (Either a b) where+ Left _ <> b = b+ a <> _ = a++instance Semigroup Ordering where+ LT <> _ = LT+ EQ <> y = y+ GT <> _ = GT++instance Semigroup b => Semigroup (a -> b) where+ f <> g = \a -> f a <> g a++instance Semigroup All where+ All a <> All b = All (a && b)++instance Semigroup Any where+ Any a <> Any b = Any (a || b)++instance (Semigroup a, Semigroup b) => Semigroup (a, b) where+ (a,b) <> (a',b') = (a<>a',b<>b')++instance (Semigroup a, Semigroup b, Semigroup c)+ => Semigroup (a, b, c) where+ (a,b,c) <> (a',b',c') = (a<>a',b<>b',c<>c')++instance (Semigroup a, Semigroup b, Semigroup c, Semigroup d)+ => Semigroup (a, b, c, d) where+ (a,b,c,d) <> (a',b',c',d') = (a<>a',b<>b',c<>c',d<>d')++instance (Semigroup a, Semigroup b, Semigroup c, Semigroup d, Semigroup e)+ => Semigroup (a, b, c, d, e) where+ (a,b,c,d,e) <> (a',b',c',d',e') = (a<>a',b<>b',c<>c',d<>d',e<>e')++-- containers instances+instance Semigroup IntSet where+ (<>) = mappend++instance Ord a => Semigroup (Set a) where+ (<>) = mappend++instance Semigroup (IntMap v) where+ (<>) = mappend++instance Ord k => Semigroup (Map k v) where+ (<>) = mappend+#endif++-- | Cabal's own 'Data.Monoid.Last' copy to avoid requiring an orphan+-- 'Binary' instance.+--+-- Once the oldest `binary` version we support provides a 'Binary'+-- instance for 'Data.Monoid.Last' we can remove this one here.+--+-- NB: 'Data.Semigroup.Last' is defined differently and not a 'Monoid'+newtype Last' a = Last' { getLast' :: Maybe a }+ deriving (Eq, Ord, Read, Show, Binary,+ Functor, App.Applicative, Generic)++instance Semigroup (Last' a) where+ x <> Last' Nothing = x+ _ <> x = x++instance Monoid (Last' a) where+ mempty = Last' Nothing+ mappend = (<>)++-------------------------------------------------------------------------------+-------------------------------------------------------------------------------+-- Stolen from Edward Kmett's BSD3-licensed `semigroups` package++-- | Generically generate a 'Semigroup' ('<>') operation for any type+-- implementing 'Generic'. This operation will append two values+-- by point-wise appending their component fields. It is only defined+-- for product types.+--+-- @+-- 'gmappend' a ('gmappend' b c) = 'gmappend' ('gmappend' a b) c+-- @+gmappend :: (Generic a, GSemigroup (Rep a)) => a -> a -> a+gmappend x y = to (gmappend' (from x) (from y))++class GSemigroup f where+ gmappend' :: f p -> f p -> f p++instance Semigroup a => GSemigroup (K1 i a) where+ gmappend' (K1 x) (K1 y) = K1 (x <> y)++instance GSemigroup f => GSemigroup (M1 i c f) where+ gmappend' (M1 x) (M1 y) = M1 (gmappend' x y)++instance (GSemigroup f, GSemigroup g) => GSemigroup (f :*: g) where+ gmappend' (x1 :*: x2) (y1 :*: y2) = gmappend' x1 y1 :*: gmappend' x2 y2++-- | Generically generate a 'Monoid' 'mempty' for any product-like type+-- implementing 'Generic'.+--+-- It is only defined for product types.+--+-- @+-- 'gmappend' 'gmempty' a = a = 'gmappend' a 'gmempty'+-- @++gmempty :: (Generic a, GMonoid (Rep a)) => a+gmempty = to gmempty'++class GSemigroup f => GMonoid f where+ gmempty' :: f p++instance (Semigroup a, Monoid a) => GMonoid (K1 i a) where+ gmempty' = K1 mempty++instance GMonoid f => GMonoid (M1 i c f) where+ gmempty' = M1 gmempty'++instance (GMonoid f, GMonoid g) => GMonoid (f :*: g) where+ gmempty' = gmempty' :*: gmempty'
− Distribution/Compat/TempFile.hs
@@ -1,128 +0,0 @@-{-# LANGUAGE CPP #-}-{-# OPTIONS_HADDOCK hide #-}-module Distribution.Compat.TempFile (- openTempFile,- openBinaryTempFile,- openNewBinaryFile,- createTempDirectory,- ) where---import System.FilePath ((</>))-import Foreign.C (eEXIST)--import System.IO (Handle, openTempFile, openBinaryTempFile)-import Data.Bits ((.|.))-import System.Posix.Internals (c_open, c_close, o_CREAT, o_EXCL, o_RDWR,- o_BINARY, o_NONBLOCK, o_NOCTTY)-import System.IO.Error (isAlreadyExistsError)-import System.Posix.Internals (withFilePath)-import Foreign.C (CInt)-import GHC.IO.Handle.FD (fdToHandle)-import Distribution.Compat.Exception (tryIO)-import Control.Exception (onException)-import Foreign.C (getErrno, errnoToIOError)--import System.Posix.Internals (c_getpid)--#if defined(mingw32_HOST_OS) || defined(ghcjs_HOST_OS)-import System.Directory ( createDirectory )-#else-import qualified System.Posix-#endif---- --------------------------------------------------------------- * temporary files--- ---------------------------------------------------------------- This is here for Haskell implementations that do not come with--- System.IO.openTempFile. This includes nhc-1.20, hugs-2006.9.--- TODO: Not sure about JHC--- TODO: This file should probably be removed.---- This is a copy/paste of the openBinaryTempFile definition, but--- if uses 666 rather than 600 for the permissions. The base library--- needs to be changed to make this better.-openNewBinaryFile :: FilePath -> String -> IO (FilePath, Handle)-openNewBinaryFile dir template = do- pid <- c_getpid- findTempName pid- where- -- We split off the last extension, so we can use .foo.ext files- -- for temporary files (hidden on Unix OSes). Unfortunately we're- -- below file path in the hierarchy here.- (prefix,suffix) =- case break (== '.') $ reverse template of- -- First case: template contains no '.'s. Just re-reverse it.- (rev_suffix, "") -> (reverse rev_suffix, "")- -- Second case: template contains at least one '.'. Strip the- -- dot from the prefix and prepend it to the suffix (if we don't- -- do this, the unique number will get added after the '.' and- -- thus be part of the extension, which is wrong.)- (rev_suffix, '.':rest) -> (reverse rest, '.':reverse rev_suffix)- -- Otherwise, something is wrong, because (break (== '.')) should- -- always return a pair with either the empty string or a string- -- beginning with '.' as the second component.- _ -> error "bug in System.IO.openTempFile"-- oflags = rw_flags .|. o_EXCL .|. o_BINARY-- findTempName x = do- fd <- withFilePath filepath $ \ f ->- c_open f oflags 0o666- if fd < 0- then do- errno <- getErrno- if errno == eEXIST- then findTempName (x+1)- else ioError (errnoToIOError "openNewBinaryFile" errno Nothing (Just dir))- else do- -- TODO: We want to tell fdToHandle what the file path is,- -- as any exceptions etc will only be able to report the- -- FD currently- h <- fdToHandle fd `onException` c_close fd- return (filepath, h)- where- filename = prefix ++ show x ++ suffix- filepath = dir `combine` filename-- -- FIXME: bits copied from System.FilePath- combine a b- | null b = a- | null a = b- | last a == pathSeparator = a ++ b- | otherwise = a ++ [pathSeparator] ++ b---- FIXME: Should use System.FilePath library-pathSeparator :: Char-#ifdef mingw32_HOST_OS-pathSeparator = '\\'-#else-pathSeparator = '/'-#endif---- FIXME: Copied from GHC.Handle-std_flags, output_flags, rw_flags :: CInt-std_flags = o_NONBLOCK .|. o_NOCTTY-output_flags = std_flags .|. o_CREAT-rw_flags = output_flags .|. o_RDWR--createTempDirectory :: FilePath -> String -> IO FilePath-createTempDirectory dir template = do- pid <- c_getpid- findTempName pid- where- findTempName x = do- let dirpath = dir </> template ++ "-" ++ show x- r <- tryIO $ mkPrivateDir dirpath- case r of- Right _ -> return dirpath- Left e | isAlreadyExistsError e -> findTempName (x+1)- | otherwise -> ioError e--mkPrivateDir :: String -> IO ()-#if defined(mingw32_HOST_OS) || defined(ghcjs_HOST_OS)-mkPrivateDir s = createDirectory s-#else-mkPrivateDir s = System.Posix.createDirectory s 0o700-#endif
Distribution/Compiler.hs view
@@ -42,15 +42,15 @@ AbiTag(..), abiTagString ) where -import Distribution.Compat.Binary (Binary)+import Distribution.Compat.Binary+import Language.Haskell.Extension+ import Data.Data (Data) import Data.Typeable (Typeable) import Data.Maybe (fromMaybe) import Distribution.Version (Version(..)) import GHC.Generics (Generic) -import Language.Haskell.Extension (Language, Extension)- import qualified System.Info (compilerName, compilerVersion) import Distribution.Text (Text(..), display) import qualified Distribution.Compat.ReadP as Parse@@ -180,7 +180,7 @@ data AbiTag = NoAbiTag | AbiTag String- deriving (Generic, Show, Read)+ deriving (Eq, Generic, Show, Read) instance Binary AbiTag
Distribution/InstalledPackageInfo.hs view
@@ -27,7 +27,9 @@ -- This module is meant to be local-only to Distribution... module Distribution.InstalledPackageInfo (- InstalledPackageInfo_(..), InstalledPackageInfo,+ InstalledPackageInfo(..),+ installedComponentId,+ installedPackageId, OriginalModule(..), ExposedModule(..), ParseResult(..), PError(..), PWarning, emptyInstalledPackageInfo,@@ -39,42 +41,30 @@ ) where import Distribution.ParseUtils- ( FieldDescr(..), ParseResult(..), PError(..), PWarning- , simpleField, listField, parseLicenseQ- , showFields, showSingleNamedField, showSimpleSingleNamedField- , parseFieldsFlat- , parseFilePathQ, parseTokenQ, parseModuleNameQ, parsePackageNameQ- , showFilePath, showToken, boolField, parseOptVersion- , parseFreeText, showFreeText, parseOptCommaList )-import Distribution.License ( License(..) )-import Distribution.Package- ( PackageName(..), PackageIdentifier(..)- , PackageId, InstalledPackageId(..)- , packageName, packageVersion, PackageKey(..) )+import Distribution.License+import Distribution.Package hiding (installedUnitId, installedPackageId) import qualified Distribution.Package as Package import Distribution.ModuleName- ( ModuleName ) import Distribution.Version- ( Version(..) ) import Distribution.Text- ( Text(disp, parse) )-import Text.PrettyPrint as Disp import qualified Distribution.Compat.ReadP as Parse+import Distribution.Compat.Binary -import Distribution.Compat.Binary (Binary)+import Text.PrettyPrint as Disp import Data.Maybe (fromMaybe) import GHC.Generics (Generic) -- ----------------------------------------------------------------------------- -- The InstalledPackageInfo type --data InstalledPackageInfo_ m+-- For BC reasons, we continue to name this record an InstalledPackageInfo;+-- but it would more accurately be called an InstalledUnitInfo with Backpack+data InstalledPackageInfo = InstalledPackageInfo { -- these parts are exactly the same as PackageDescription- installedPackageId :: InstalledPackageId,- sourcePackageId :: PackageId,- packageKey :: PackageKey,+ sourcePackageId :: PackageId,+ installedUnitId :: UnitId,+ compatPackageKey :: String, license :: License, copyright :: String, maintainer :: String,@@ -86,10 +76,10 @@ description :: String, category :: String, -- these parts are required by an installed package only:+ abiHash :: AbiHash, exposed :: Bool, exposedModules :: [ExposedModule],- instantiatedWith :: [(m, OriginalModule)],- hiddenModules :: [m],+ hiddenModules :: [ModuleName], trusted :: Bool, importDirs :: [FilePath], libraryDirs :: [FilePath],@@ -99,7 +89,7 @@ extraGHCiLibraries:: [String], -- overrides extraLibraries for GHCi includeDirs :: [FilePath], includes :: [String],- depends :: [InstalledPackageId],+ depends :: [UnitId], ccOptions :: [String], ldOptions :: [String], frameworkDirs :: [FilePath],@@ -108,26 +98,34 @@ haddockHTMLs :: [FilePath], pkgRoot :: Maybe FilePath }- deriving (Generic, Read, Show)+ deriving (Eq, Generic, Read, Show) -instance Binary m => Binary (InstalledPackageInfo_ m)+installedComponentId :: InstalledPackageInfo -> ComponentId+installedComponentId ipi = case installedUnitId ipi of+ SimpleUnitId cid -> cid -instance Package.Package (InstalledPackageInfo_ str) where+{-# DEPRECATED installedPackageId "Use installedUnitId instead" #-}+-- | Backwards compatibility with Cabal pre-1.24.+installedPackageId :: InstalledPackageInfo -> UnitId+installedPackageId = installedUnitId++instance Binary InstalledPackageInfo++instance Package.Package InstalledPackageInfo where packageId = sourcePackageId -instance Package.PackageInstalled (InstalledPackageInfo_ str) where- installedPackageId = installedPackageId- installedDepends = depends+instance Package.HasUnitId InstalledPackageInfo where+ installedUnitId = installedUnitId -type InstalledPackageInfo = InstalledPackageInfo_ ModuleName+instance Package.PackageInstalled InstalledPackageInfo where+ installedDepends = depends -emptyInstalledPackageInfo :: InstalledPackageInfo_ m+emptyInstalledPackageInfo :: InstalledPackageInfo emptyInstalledPackageInfo = InstalledPackageInfo {- installedPackageId = InstalledPackageId "",- sourcePackageId = PackageIdentifier (PackageName "") noVersion,- packageKey = OldPackageKey (PackageIdentifier- (PackageName "") noVersion),+ sourcePackageId = PackageIdentifier (PackageName "") (Version [] []),+ installedUnitId = mkUnitId "",+ compatPackageKey = "", license = UnspecifiedLicense, copyright = "", maintainer = "",@@ -138,10 +136,10 @@ synopsis = "", description = "", category = "",+ abiHash = AbiHash "", exposed = False, exposedModules = [], hiddenModules = [],- instantiatedWith = [], trusted = False, importDirs = [], libraryDirs = [],@@ -161,15 +159,12 @@ pkgRoot = Nothing } -noVersion :: Version-noVersion = Version [] []- -- ----------------------------------------------------------------------------- -- Exposed modules data OriginalModule = OriginalModule {- originalPackageId :: InstalledPackageId,+ originalPackageId :: UnitId, originalModuleName :: ModuleName } deriving (Generic, Eq, Read, Show)@@ -177,10 +172,9 @@ data ExposedModule = ExposedModule { exposedName :: ModuleName,- exposedReexport :: Maybe OriginalModule,- exposedSignature :: Maybe OriginalModule -- This field is unused for now.+ exposedReexport :: Maybe OriginalModule }- deriving (Generic, Read, Show)+ deriving (Eq, Generic, Read, Show) instance Text OriginalModule where disp (OriginalModule ipi m) =@@ -192,14 +186,11 @@ return (OriginalModule ipi m) instance Text ExposedModule where- disp (ExposedModule m reexport signature) =+ disp (ExposedModule m reexport) = Disp.sep [ disp m , case reexport of Just m' -> Disp.sep [Disp.text "from", disp m'] Nothing -> Disp.empty- , case signature of- Just m' -> Disp.sep [Disp.text "is", disp m']- Nothing -> Disp.empty ] parse = do m <- parseModuleNameQ@@ -208,12 +199,7 @@ _ <- Parse.string "from" Parse.skipSpaces fmap Just parse- Parse.skipSpaces- signature <- Parse.option Nothing $ do- _ <- Parse.string "is"- Parse.skipSpaces- fmap Just parse- return (ExposedModule m reexport signature)+ return (ExposedModule m reexport) instance Binary OriginalModule@@ -229,7 +215,7 @@ showExposedModules xs | all isExposedModule xs = fsep (map disp xs) | otherwise = fsep (Disp.punctuate comma (map disp xs))- where isExposedModule (ExposedModule _ Nothing Nothing) = True+ where isExposedModule (ExposedModule _ Nothing) = True isExposedModule _ = False parseExposedModules :: Parse.ReadP r [ExposedModule]@@ -243,14 +229,6 @@ parseFieldsFlat (fieldsInstalledPackageInfo ++ deprecatedFieldDescrs) emptyInstalledPackageInfo -parseInstantiatedWith :: Parse.ReadP r (ModuleName, OriginalModule)-parseInstantiatedWith = do k <- parse- _ <- Parse.char '='- n <- parse- _ <- Parse.char '@'- p <- parse- return (k, OriginalModule p n)- -- ----------------------------------------------------------------------------- -- Pretty-printing @@ -263,9 +241,6 @@ showSimpleInstalledPackageInfoField :: String -> Maybe (InstalledPackageInfo -> String) showSimpleInstalledPackageInfoField = showSimpleSingleNamedField fieldsInstalledPackageInfo -showInstantiatedWith :: (ModuleName, OriginalModule) -> Doc-showInstantiatedWith (k, OriginalModule p m) = disp k <> text "=" <> disp m <> text "@" <> disp p- -- ----------------------------------------------------------------------------- -- Description of the fields, for parsing/printing @@ -282,10 +257,11 @@ packageVersion (\ver pkg -> pkg{sourcePackageId=(sourcePackageId pkg){pkgVersion=ver}}) , simpleField "id" disp parse- installedPackageId (\ipid pkg -> pkg{installedPackageId=ipid})+ installedUnitId (\pk pkg -> pkg{installedUnitId=pk})+ -- NB: parse these as component IDs , simpleField "key"- disp parse- packageKey (\ipid pkg -> pkg{packageKey=ipid})+ (disp . ComponentId) (fmap (\(ComponentId s) -> s) parse)+ compatPackageKey (\pk pkg -> pkg{compatPackageKey=pk}) , simpleField "license" disp parseLicenseQ license (\l pkg -> pkg{license=l})@@ -328,9 +304,9 @@ , listField "hidden-modules" disp parseModuleNameQ hiddenModules (\xs pkg -> pkg{hiddenModules=xs})- , listField "instantiated-with"- showInstantiatedWith parseInstantiatedWith- instantiatedWith (\xs pkg -> pkg{instantiatedWith=xs})+ , simpleField "abi"+ disp parse+ abiHash (\abi pkg -> pkg{abiHash=abi}) , boolField "trusted" trusted (\val pkg -> pkg{trusted=val}) , listField "import-dirs"
+ Distribution/Lex.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE PatternGuards #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Lex+-- Copyright : Ben Gamari 2015-2019+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module contains a simple lexer supporting quoted strings++module Distribution.Lex (+ tokenizeQuotedWords+ ) where++import Data.Char (isSpace)+import Distribution.Compat.Semigroup as Semi++newtype DList a = DList ([a] -> [a])++runDList :: DList a -> [a]+runDList (DList run) = run []++singleton :: a -> DList a+singleton a = DList (a:)++instance Monoid (DList a) where+ mempty = DList id+ mappend = (Semi.<>)++instance Semigroup (DList a) where+ DList a <> DList b = DList (a . b)++tokenizeQuotedWords :: String -> [String]+tokenizeQuotedWords = filter (not . null) . go False mempty+ where+ go :: Bool -- ^ in quoted region+ -> DList Char -- ^ accumulator+ -> String -- ^ string to be parsed+ -> [String] -- ^ parse result+ go _ accum []+ | [] <- accum' = []+ | otherwise = [accum']+ where accum' = runDList accum++ go False accum (c:cs)+ | isSpace c = runDList accum : go False mempty cs+ | c == '"' = go True accum cs++ go True accum (c:cs)+ | c == '"' = go False accum cs++ go quoted accum (c:cs)+ = go quoted (accum `mappend` singleton c) cs+
Distribution/License.hs view
@@ -47,13 +47,13 @@ knownLicenses, ) where -import Distribution.Version (Version(Version))--import Distribution.Text (Text(..), display)+import Distribution.Version+import Distribution.Text import qualified Distribution.Compat.ReadP as Parse+import Distribution.Compat.Binary+ import qualified Text.PrettyPrint as Disp import Text.PrettyPrint ((<>))-import Distribution.Compat.Binary (Binary) import qualified Data.Char as Char (isAlphaNum) import Data.Data (Data) import Data.Typeable (Typeable)
Distribution/Make.hs view
@@ -62,22 +62,19 @@ -- local import Distribution.Compat.Exception-import Distribution.Package --must not specify imports, since we're exporting moule.-import Distribution.Simple.Program(defaultProgramConfiguration)+import Distribution.Package+import Distribution.Simple.Program import Distribution.PackageDescription import Distribution.Simple.Setup import Distribution.Simple.Command -import Distribution.Simple.Utils (rawSystemExit, cabalVersion)+import Distribution.Simple.Utils -import Distribution.License (License(..))+import Distribution.License import Distribution.Version- ( Version(..) ) import Distribution.Text- ( display ) import System.Environment (getArgs, getProgName)-import Data.List (intercalate) import System.Exit defaultMain :: IO ()
Distribution/ModuleName.hs view
@@ -22,14 +22,13 @@ ) where import Distribution.Text- ( Text(..) )+import Distribution.Compat.Binary+import qualified Distribution.Compat.ReadP as Parse -import Distribution.Compat.Binary (Binary) import qualified Data.Char as Char ( isAlphaNum, isUpper ) import Data.Data (Data) import Data.Typeable (Typeable)-import qualified Distribution.Compat.ReadP as Parse import qualified Text.PrettyPrint as Disp import Data.List ( intercalate, intersperse )
Distribution/Package.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} ----------------------------------------------------------------------------- -- |@@ -21,14 +22,16 @@ PackageIdentifier(..), PackageId, - -- * Installed package identifiers- InstalledPackageId(..),+ -- * Package keys/installed package IDs (used for linker symbols)+ ComponentId(..),+ UnitId(..),+ mkUnitId,+ mkLegacyUnitId,+ getHSLibraryName,+ InstalledPackageId, -- backwards compat - -- * Package keys (used for linker symbols and library name)- PackageKey(..),- mkPackageKey,- packageKeyHash,- packageKeyLibraryName,+ -- * ABI hash+ AbiHash(..), -- * Package source dependencies Dependency(..),@@ -38,32 +41,28 @@ -- * Package classes Package(..), packageName, packageVersion,- PackageFixedDeps(..),+ HasUnitId(..),+ installedPackageId, PackageInstalled(..), ) where -import Distribution.ModuleName ( ModuleName ) import Distribution.Version ( Version(..), VersionRange, anyVersion, thisVersion , notThisVersion, simplifyVersionRange ) -import Distribution.Text (Text(..), display) import qualified Distribution.Compat.ReadP as Parse-import Distribution.Compat.ReadP ((<++)) import qualified Text.PrettyPrint as Disp+import Distribution.Compat.ReadP+import Distribution.Compat.Binary+import Distribution.Text import Control.DeepSeq (NFData(..))-import Data.Ord ( comparing )-import Distribution.Compat.Binary (Binary) import qualified Data.Char as Char- ( isDigit, isAlphaNum, isUpper, isLower, ord, chr )+ ( isDigit, isAlphaNum, ) import Data.Data ( Data )-import Data.List ( intercalate, foldl', sortBy )+import Data.List ( intercalate ) import Data.Typeable ( Typeable )-import Data.Word ( Word64 )-import GHC.Fingerprint ( Fingerprint(..), fingerprintString ) import GHC.Generics (Generic)-import Numeric ( showIntAtBase ) import Text.PrettyPrint ((<>), (<+>), text) newtype PackageName = PackageName { unPackageName :: String }@@ -113,192 +112,47 @@ rnf (PackageIdentifier name version) = rnf name `seq` rnf version -- --------------------------------------------------------------- * Installed Package Ids--- ---------------------------------------------------------------- | An InstalledPackageId uniquely identifies an instance of an installed--- package. There can be at most one package with a given 'InstalledPackageId'--- in a package database, or overlay of databases.----newtype InstalledPackageId = InstalledPackageId String- deriving (Generic, Read,Show,Eq,Ord,Typeable,Data)--instance Binary InstalledPackageId--instance Text InstalledPackageId where- disp (InstalledPackageId str) = text str-- parse = InstalledPackageId `fmap` Parse.munch1 abi_char- where abi_char c = Char.isAlphaNum c || c `elem` "-_."---- --------------------------------------------------------------- * Package Keys+-- * Component Source Hash -- ------------------------------------------------------------ --- | A 'PackageKey' is the notion of "package ID" which is visible to the--- compiler. Why is this not a 'PackageId'? The 'PackageId' is a user-visible--- concept written explicity in Cabal files; on the other hand, a 'PackageKey'--- may contain, for example, information about the transitive dependency--- tree of a package. Why is this not an 'InstalledPackageId'? A 'PackageKey'--- affects the ABI because it is used for linker symbols; however, an--- 'InstalledPackageId' can be used to distinguish two ABI-compatible versions--- of a library.------ The key is defined to be a 128-bit MD5 hash, separated into two 64-bit--- components (the most significant component coming first) which are--- individually base-62 encoded (A-Z, a-z, 0-9).------ @--- key ::= hash64 hash64--- hash64 ::= [A-Za-z0-9]{11}--- @------ The string that is hashed is specified as raw_key:------ @--- raw_key ::= package_id "\n"--- holes_nl--- depends_nl--- package_id ::= package_name "-" package_version--- holes_nl ::= ""--- | hole_inst "\n" holes_nl--- hole_inst ::= modulename " " key ":" modulename--- depends_nl ::= ""--- | depend "\n" depends_nl--- depend ::= key--- @------ The holes list MUST be sorted by the first modulename; the depends list--- MUST be sorted by the key. holes describes the backing implementations of--- all holes in the package; depends describes all of the build-depends of--- a package. A package key MAY be used in holes even if it is not--- mentioned in depends: depends contains STRICTLY packages which are--- textually mentioned in the package description.------ The trailing newline is MANDATORY.------ There is also a variant of package key which is prefixed by a informational--- string. This key MUST NOT be used in the computation of the hash proper,--- but it is useful for human-readable consumption.------ @--- infokey ::= infostring "_" key--- infostring ::= [A-Za-z0-9-]+--- @------ For example, Cabal provides a key with the first five characters of the--- package name for linker symbols.+-- | A 'ComponentId' uniquely identifies the transitive source+-- code closure of a component. For non-Backpack components, it also+-- serves as the basis for install paths, symbols, etc. ---data PackageKey- -- | Modern package key which is a hash of the PackageId and the transitive- -- dependency key. Manually inline it here so we can get the instances- -- we need. Also contains a short informative string- = PackageKey !String {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64- -- | Old-style package key which is just a 'PackageId'. Required because- -- old versions of GHC assume that the 'sourcePackageId' recorded for an- -- installed package coincides with the package key it was compiled with.- | OldPackageKey !PackageId+data ComponentId+ = ComponentId String deriving (Generic, Read, Show, Eq, Ord, Typeable, Data) -instance Binary PackageKey---- | Convenience function which converts a fingerprint into a new-style package--- key.-fingerprintPackageKey :: String -> Fingerprint -> PackageKey-fingerprintPackageKey s (Fingerprint a b) = PackageKey s a b---- | Generates a 'PackageKey' from a 'PackageId', sorted package keys of the--- immediate dependencies.-mkPackageKey :: Bool -- are modern style package keys supported?- -> PackageId- -> [PackageKey] -- dependencies- -> [(ModuleName, (PackageKey, ModuleName))] -- hole instantiations- -> PackageKey-mkPackageKey True pid deps holes =- fingerprintPackageKey stubName . fingerprintString $- display pid ++ "\n" ++- -- NB: packageKeyHash, NOT display- concat [ display m ++ " " ++ packageKeyHash p' ++ ":" ++ display m' ++ "\n"- | (m, (p', m')) <- sortBy (comparing fst) holes] ++- concat [ packageKeyHash d ++ "\n"- | d <- sortBy (comparing packageKeyHash) deps]- where stubName = take 5 (filter (/= '-') (unPackageName (pkgName pid)))-mkPackageKey False pid _ _ = OldPackageKey pid---- The base-62 code is based off of 'locators'--- ((c) Operational Dynamics Consulting, BSD3 licensed)---- Note: Instead of base-62 encoding a single 128-bit integer--- (ceil(21.49) characters), we'll base-62 a pair of 64-bit integers--- (2 * ceil(10.75) characters). Luckily for us, it's the same number of--- characters! In the long term, this should go in GHC.Fingerprint,--- but not now...---- | Size of a 64-bit word when written as a base-62 string-word64Base62Len :: Int-word64Base62Len = 11---- | Converts a 64-bit word into a base-62 string-toBase62 :: Word64 -> String-toBase62 w = pad ++ str- where- pad = replicate len '0'- len = word64Base62Len - length str -- 11 == ceil(64 / lg 62)- str = showIntAtBase 62 represent w ""- represent :: Int -> Char- represent x- | x < 10 = Char.chr (48 + x)- | x < 36 = Char.chr (65 + x - 10)- | x < 62 = Char.chr (97 + x - 36)- | otherwise = error ("represent (base 62): impossible!")+{-# DEPRECATED InstalledPackageId "Use UnitId instead" #-}+type InstalledPackageId = UnitId --- | Parses a base-62 string into a 64-bit word-fromBase62 :: String -> Word64-fromBase62 ss = foldl' multiply 0 ss- where- value :: Char -> Int- value c- | Char.isDigit c = Char.ord c - 48- | Char.isUpper c = Char.ord c - 65 + 10- | Char.isLower c = Char.ord c - 97 + 36- | otherwise = error ("value (base 62): impossible!")+instance Binary ComponentId - multiply :: Word64 -> Char -> Word64- multiply acc c = acc * 62 + (fromIntegral $ value c)+instance Text ComponentId where+ disp (ComponentId str) = text str --- | Parses a base-62 string into a fingerprint.-readBase62Fingerprint :: String -> Fingerprint-readBase62Fingerprint s = Fingerprint w1 w2- where (s1,s2) = splitAt word64Base62Len s- w1 = fromBase62 s1- w2 = fromBase62 (take word64Base62Len s2)+ parse = ComponentId `fmap` Parse.munch1 abi_char+ where abi_char c = Char.isAlphaNum c || c `elem` "-_." -packageKeyHash :: PackageKey -> String-packageKeyHash (PackageKey _ w1 w2) = toBase62 w1 ++ toBase62 w2-packageKeyHash (OldPackageKey pid) = display pid+instance NFData ComponentId where+ rnf (ComponentId pk) = rnf pk -packageKeyLibraryName :: PackageId -> PackageKey -> String-packageKeyLibraryName pid (PackageKey _ w1 w2) = display pid ++ "-" ++ toBase62 w1 ++ toBase62 w2-packageKeyLibraryName _ (OldPackageKey pid) = display pid+-- | Returns library name prefixed with HS, suitable for filenames+getHSLibraryName :: UnitId -> String+getHSLibraryName (SimpleUnitId (ComponentId s)) = "HS" ++ s -instance Text PackageKey where- disp (PackageKey prefix w1 w2) = Disp.text prefix <> Disp.char '_'- <> Disp.text (toBase62 w1) <> Disp.text (toBase62 w2)- disp (OldPackageKey pid) = disp pid+-- | For now, there is no distinction between component IDs+-- and unit IDs in Cabal.+newtype UnitId = SimpleUnitId ComponentId+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data, Binary, Text, NFData) - parse = parseNew <++ parseOld- where parseNew = do- prefix <- Parse.munch1 (\c -> Char.isAlphaNum c || c `elem` "-")- _ <- Parse.char '_' -- if we use '-' it's ambiguous- fmap (fingerprintPackageKey prefix . readBase62Fingerprint)- . Parse.count (word64Base62Len * 2)- $ Parse.satisfy Char.isAlphaNum- parseOld = do pid <- parse- return (OldPackageKey pid)+-- | Makes a simple-style UnitId from a string.+mkUnitId :: String -> UnitId+mkUnitId = SimpleUnitId . ComponentId -instance NFData PackageKey where- rnf (PackageKey prefix _ _) = rnf prefix- rnf (OldPackageKey pid) = rnf pid+-- | Make an old-style UnitId from a package identifier+mkLegacyUnitId :: PackageId -> UnitId+mkLegacyUnitId = SimpleUnitId . ComponentId . display -- ------------------------------------------------------------ -- * Package source dependencies@@ -358,22 +212,31 @@ instance Package PackageIdentifier where packageId = id --- | Subclass of packages that have specific versioned dependencies.------ So for example a not-yet-configured package has dependencies on version--- ranges, not specific versions. A configured or an already installed package--- depends on exact versions. Some operations or data structures (like--- dependency graphs) only make sense on this subclass of package types.----class Package pkg => PackageFixedDeps pkg where- depends :: pkg -> [PackageIdentifier]+-- | Packages that have an installed package ID+class Package pkg => HasUnitId pkg where+ installedUnitId :: pkg -> UnitId +{-# DEPRECATED installedPackageId "Use installedUnitId instead" #-}+-- | Compatibility wrapper for Cabal pre-1.24.+installedPackageId :: HasUnitId pkg => pkg -> UnitId+installedPackageId = installedUnitId+ -- | Class of installed packages. -- -- The primary data type which is an instance of this package is -- 'InstalledPackageInfo', but when we are doing install plans in Cabal install -- we may have other, installed package-like things which contain more metadata. -- Installed packages have exact dependencies 'installedDepends'.-class Package pkg => PackageInstalled pkg where- installedPackageId :: pkg -> InstalledPackageId- installedDepends :: pkg -> [InstalledPackageId]+class (HasUnitId pkg) => PackageInstalled pkg where+ installedDepends :: pkg -> [UnitId]++-- -----------------------------------------------------------------------------+-- ABI hash++newtype AbiHash = AbiHash String+ deriving (Eq, Show, Read, Generic)+instance Binary AbiHash++instance Text AbiHash where+ disp (AbiHash abi) = Disp.text abi+ parse = fmap AbiHash (Parse.munch Char.isAlphaNum)
Distribution/PackageDescription.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} @@ -98,46 +97,47 @@ GenericPackageDescription(..), Flag(..), FlagName(..), FlagAssignment, CondTree(..), ConfVar(..), Condition(..),+ cNot, cAnd, cOr, -- * Source repositories SourceRepo(..), RepoKind(..), RepoType(..), knownRepoTypes,++ -- * Custom setup build information+ SetupBuildInfo(..), ) where -import Distribution.Compat.Binary (Binary)-import Data.Data (Data)-import Data.List (nub, intercalate)-import Data.Maybe (fromMaybe, maybeToList)-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid (Monoid(mempty, mappend))-#endif-import Data.Typeable ( Typeable )-import Control.Monad (MonadPlus(mplus))-import GHC.Generics (Generic)-import Text.PrettyPrint as Disp+import Distribution.Compat.Binary+import qualified Distribution.Compat.Semigroup as Semi ((<>))+import Distribution.Compat.Semigroup as Semi (Monoid(..), Semigroup, gmempty) import qualified Distribution.Compat.ReadP as Parse-import Distribution.Compat.ReadP ((<++))-import qualified Data.Char as Char (isAlphaNum, isDigit, toLower)-import qualified Data.Map as Map-import Data.Map (Map)-+import Distribution.Compat.ReadP ((<++)) import Distribution.Package- ( PackageName(PackageName), PackageIdentifier(PackageIdentifier)- , Dependency, Package(..), PackageName, packageName )-import Distribution.ModuleName ( ModuleName )+import Distribution.ModuleName import Distribution.Version- ( Version(Version), VersionRange, anyVersion, orLaterVersion- , asVersionIntervals, LowerBound(..) )-import Distribution.License (License(UnspecifiedLicense))-import Distribution.Compiler (CompilerFlavor)-import Distribution.System (OS, Arch)+import Distribution.License+import Distribution.Compiler+import Distribution.System import Distribution.Text- ( Text(..), display ) import Language.Haskell.Extension- ( Language, Extension ) +import Data.Data (Data)+import Data.Foldable (traverse_)+import Data.List (nub, intercalate)+import Data.Maybe (fromMaybe, maybeToList)+import Data.Foldable as Fold (Foldable(foldMap))+import Data.Traversable as Trav (Traversable(traverse))+import Data.Typeable ( Typeable )+import Control.Applicative as AP (Alternative(..), Applicative(..))+import Control.Monad (MonadPlus(mplus,mzero), ap)+import GHC.Generics (Generic)+import Text.PrettyPrint as Disp+import qualified Data.Char as Char (isAlphaNum, isDigit, toLower)+import qualified Data.Map as Map+import Data.Map (Map)+ -- ----------------------------------------------------------------------------- -- The PackageDescription type @@ -168,6 +168,7 @@ customFieldsPD :: [(String,String)], -- ^Custom fields starting -- with x-, stored in a -- simple assoc-list.+ -- | YOU PROBABLY DON'T WANT TO USE THIS FIELD. This field is -- special! Depending on how far along processing the -- PackageDescription we are, the contents of this field are@@ -186,6 +187,7 @@ -- transitioning to specifying just a single version, not a range. specVersionRaw :: Either Version VersionRange, buildType :: Maybe BuildType,+ setupBuildInfo :: Maybe SetupBuildInfo, -- components library :: Maybe Library, executables :: [Executable],@@ -253,6 +255,7 @@ description = "", category = "", customFieldsPD = [],+ setupBuildInfo = Nothing, library = Nothing, executables = [], testSuites = [],@@ -298,6 +301,33 @@ _ -> UnknownBuildType name -- ---------------------------------------------------------------------------+-- The SetupBuildInfo type++-- One can see this as a very cut-down version of BuildInfo below.+-- To keep things simple for tools that compile Setup.hs we limit the+-- options authors can specify to just Haskell package dependencies.++data SetupBuildInfo = SetupBuildInfo {+ setupDepends :: [Dependency],+ defaultSetupDepends :: Bool+ -- ^ Is this a default 'custom-setup' section added by the cabal-install+ -- code (as opposed to user-provided)? This field is only used+ -- internally, and doesn't correspond to anything in the .cabal+ -- file. See #3199.+ }+ deriving (Generic, Show, Eq, Read, Typeable, Data)++instance Binary SetupBuildInfo++instance Semi.Monoid SetupBuildInfo where+ mempty = SetupBuildInfo [] False+ mappend = (Semi.<>)++instance Semigroup SetupBuildInfo where+ a <> b = SetupBuildInfo (setupDepends a Semi.<> setupDepends b)+ (defaultSetupDepends a || defaultSetupDepends b)++-- --------------------------------------------------------------------------- -- Module renaming -- | Renaming applied to the modules provided by a package.@@ -313,18 +343,18 @@ defaultRenaming = ModuleRenaming True [] lookupRenaming :: Package pkg => pkg -> Map PackageName ModuleRenaming -> ModuleRenaming-lookupRenaming pkg rns =- Map.findWithDefault- (error ("lookupRenaming: missing renaming for " ++ display (packageName pkg)))- (packageName pkg) rns+lookupRenaming = Map.findWithDefault defaultRenaming . packageName instance Binary ModuleRenaming where instance Monoid ModuleRenaming where- ModuleRenaming b rns `mappend` ModuleRenaming b' rns'- = ModuleRenaming (b || b') (rns ++ rns') -- ToDo: dedupe? mempty = ModuleRenaming False []+ mappend = (Semi.<>) +instance Semigroup ModuleRenaming where+ ModuleRenaming b rns <> ModuleRenaming b' rns'+ = ModuleRenaming (b || b') (rns ++ rns') -- ToDo: dedupe?+ -- NB: parentheses are mandatory, because later we may extend this syntax -- to allow "hiding (A, B)" or other modifier words. instance Text ModuleRenaming where@@ -383,7 +413,10 @@ libExposed = True, libBuildInfo = mempty }- mappend a b = Library {+ mappend = (Semi.<>)++instance Semigroup Library where+ a <> b = Library { exposedModules = combine exposedModules, reexportedModules = combine reexportedModules, requiredSignatures = combine requiredSignatures,@@ -411,7 +444,7 @@ -- function with the library build info as argument. withLib :: PackageDescription -> (Library -> IO ()) -> IO () withLib pkg_descr f =- maybe (return ()) f (maybeHasLibs pkg_descr)+ traverse_ f (maybeHasLibs pkg_descr) -- | Get all the module names from the library (exposed and internal modules) -- which need to be compiled. (This does not include reexports, which@@ -444,7 +477,7 @@ parse = do mpkgname <- Parse.option Nothing $ do- pkgname <- parse + pkgname <- parse _ <- Parse.char ':' return (Just pkgname) origname <- parse@@ -468,12 +501,11 @@ instance Binary Executable instance Monoid Executable where- mempty = Executable {- exeName = mempty,- modulePath = mempty,- buildInfo = mempty- }- mappend a b = Executable{+ mempty = gmempty+ mappend = (Semi.<>)++instance Semigroup Executable where+ a <> b = Executable{ exeName = combine' exeName, modulePath = combine modulePath, buildInfo = combine buildInfo@@ -558,8 +590,10 @@ testBuildInfo = mempty, testEnabled = False }+ mappend = (Semi.<>) - mappend a b = TestSuite {+instance Semigroup TestSuite where+ a <> b = TestSuite { testName = combine' testName, testInterface = combine testInterface, testBuildInfo = combine testBuildInfo,@@ -574,9 +608,12 @@ instance Monoid TestSuiteInterface where mempty = TestSuiteUnsupported (TestTypeUnknown mempty (Version [] []))- mappend a (TestSuiteUnsupported _) = a- mappend _ b = b+ mappend = (Semi.<>) +instance Semigroup TestSuiteInterface where+ a <> (TestSuiteUnsupported _) = a+ _ <> b = b+ emptyTestSuite :: TestSuite emptyTestSuite = mempty @@ -691,8 +728,10 @@ benchmarkBuildInfo = mempty, benchmarkEnabled = False }+ mappend = (Semi.<>) - mappend a b = Benchmark {+instance Semigroup Benchmark where+ a <> b = Benchmark { benchmarkName = combine' benchmarkName, benchmarkInterface = combine benchmarkInterface, benchmarkBuildInfo = combine benchmarkBuildInfo,@@ -707,9 +746,12 @@ instance Monoid BenchmarkInterface where mempty = BenchmarkUnsupported (BenchmarkTypeUnknown mempty (Version [] []))- mappend a (BenchmarkUnsupported _) = a- mappend _ b = b+ mappend = (Semi.<>) +instance Semigroup BenchmarkInterface where+ a <> (BenchmarkUnsupported _) = a+ _ <> b = b+ emptyBenchmark :: Benchmark emptyBenchmark = mempty @@ -769,6 +811,7 @@ ldOptions :: [String], -- ^ options for linker pkgconfigDepends :: [Dependency], -- ^ pkg-config packages that are used frameworks :: [String], -- ^support frameworks for Mac OS X+ extraFrameworkDirs:: [String], -- ^ extra locations to find frameworks. cSources :: [FilePath], jsSources :: [FilePath], hsSourceDirs :: [FilePath], -- ^ where to look for the Haskell module hierarchy@@ -801,63 +844,68 @@ instance Monoid BuildInfo where mempty = BuildInfo {- buildable = True,- buildTools = [],- cppOptions = [],- ccOptions = [],- ldOptions = [],- pkgconfigDepends = [],- frameworks = [],- cSources = [],- jsSources = [],- hsSourceDirs = [],- otherModules = [],- defaultLanguage = Nothing,- otherLanguages = [],- defaultExtensions = [],- otherExtensions = [],- oldExtensions = [],- extraLibs = [],- extraGHCiLibs = [],- extraLibDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- options = [],- profOptions = [],- sharedOptions = [],- customFieldsBI = [],- targetBuildDepends = [],+ buildable = True,+ buildTools = [],+ cppOptions = [],+ ccOptions = [],+ ldOptions = [],+ pkgconfigDepends = [],+ frameworks = [],+ extraFrameworkDirs = [],+ cSources = [],+ jsSources = [],+ hsSourceDirs = [],+ otherModules = [],+ defaultLanguage = Nothing,+ otherLanguages = [],+ defaultExtensions = [],+ otherExtensions = [],+ oldExtensions = [],+ extraLibs = [],+ extraGHCiLibs = [],+ extraLibDirs = [],+ includeDirs = [],+ includes = [],+ installIncludes = [],+ options = [],+ profOptions = [],+ sharedOptions = [],+ customFieldsBI = [],+ targetBuildDepends = [], targetBuildRenaming = Map.empty }- mappend a b = BuildInfo {- buildable = buildable a && buildable b,- buildTools = combine buildTools,- cppOptions = combine cppOptions,- ccOptions = combine ccOptions,- ldOptions = combine ldOptions,- pkgconfigDepends = combine pkgconfigDepends,- frameworks = combineNub frameworks,- cSources = combineNub cSources,- jsSources = combineNub jsSources,- hsSourceDirs = combineNub hsSourceDirs,- otherModules = combineNub otherModules,- defaultLanguage = combineMby defaultLanguage,- otherLanguages = combineNub otherLanguages,- defaultExtensions = combineNub defaultExtensions,- otherExtensions = combineNub otherExtensions,- oldExtensions = combineNub oldExtensions,- extraLibs = combine extraLibs,- extraGHCiLibs = combine extraGHCiLibs,- extraLibDirs = combineNub extraLibDirs,- includeDirs = combineNub includeDirs,- includes = combineNub includes,- installIncludes = combineNub installIncludes,- options = combine options,- profOptions = combine profOptions,- sharedOptions = combine sharedOptions,- customFieldsBI = combine customFieldsBI,- targetBuildDepends = combineNub targetBuildDepends,+ mappend = (Semi.<>)++instance Semigroup BuildInfo where+ a <> b = BuildInfo {+ buildable = buildable a && buildable b,+ buildTools = combine buildTools,+ cppOptions = combine cppOptions,+ ccOptions = combine ccOptions,+ ldOptions = combine ldOptions,+ pkgconfigDepends = combine pkgconfigDepends,+ frameworks = combineNub frameworks,+ extraFrameworkDirs = combineNub extraFrameworkDirs,+ cSources = combineNub cSources,+ jsSources = combineNub jsSources,+ hsSourceDirs = combineNub hsSourceDirs,+ otherModules = combineNub otherModules,+ defaultLanguage = combineMby defaultLanguage,+ otherLanguages = combineNub otherLanguages,+ defaultExtensions = combineNub defaultExtensions,+ otherExtensions = combineNub otherExtensions,+ oldExtensions = combineNub oldExtensions,+ extraLibs = combine extraLibs,+ extraGHCiLibs = combine extraGHCiLibs,+ extraLibDirs = combineNub extraLibDirs,+ includeDirs = combineNub includeDirs,+ includes = combineNub includes,+ installIncludes = combineNub installIncludes,+ options = combine options,+ profOptions = combine profOptions,+ sharedOptions = combine sharedOptions,+ customFieldsBI = combine customFieldsBI,+ targetBuildDepends = combineNub targetBuildDepends, targetBuildRenaming = combineMap targetBuildRenaming } where@@ -1102,12 +1150,12 @@ condTestSuites :: [(String, CondTree ConfVar [Dependency] TestSuite)], condBenchmarks :: [(String, CondTree ConfVar [Dependency] Benchmark)] }- deriving (Show, Eq, Typeable, Data)+ deriving (Show, Eq, Typeable, Data, Generic) instance Package GenericPackageDescription where packageId = packageId . packageDescription ---TODO: make PackageDescription an instance of Text.+instance Binary GenericPackageDescription -- | A flag can represent a feature to be included, or a way of linking -- a target against its dependencies, or in fact whatever you can think of.@@ -1117,8 +1165,10 @@ , flagDefault :: Bool , flagManual :: Bool }- deriving (Show, Eq, Typeable, Data)+ deriving (Show, Eq, Typeable, Data, Generic) +instance Binary Flag+ -- | A 'FlagName' is the name of a user-defined configuration flag newtype FlagName = FlagName String deriving (Eq, Generic, Ord, Show, Read, Typeable, Data)@@ -1137,16 +1187,96 @@ | Arch Arch | Flag FlagName | Impl CompilerFlavor VersionRange- deriving (Eq, Show, Typeable, Data)+ deriving (Eq, Show, Typeable, Data, Generic) +instance Binary ConfVar+ -- | A boolean expression parameterized over the variable type used. data Condition c = Var c | Lit Bool | CNot (Condition c) | COr (Condition c) (Condition c) | CAnd (Condition c) (Condition c)- deriving (Show, Eq, Typeable, Data)+ deriving (Show, Eq, Typeable, Data, Generic) +-- | Boolean negation of a 'Condition' value.+cNot :: Condition a -> Condition a+cNot (Lit b) = Lit (not b)+cNot (CNot c) = c+cNot c = CNot c++-- | Boolean AND of two 'Condtion' values.+cAnd :: Condition a -> Condition a -> Condition a+cAnd (Lit False) _ = Lit False+cAnd _ (Lit False) = Lit False+cAnd (Lit True) x = x+cAnd x (Lit True) = x+cAnd x y = CAnd x y++-- | Boolean OR of two 'Condition' values.+cOr :: Eq v => Condition v -> Condition v -> Condition v+cOr (Lit True) _ = Lit True+cOr _ (Lit True) = Lit True+cOr (Lit False) x = x+cOr x (Lit False) = x+cOr c (CNot d)+ | c == d = Lit True+cOr (CNot c) d+ | c == d = Lit True+cOr x y = COr x y++instance Functor Condition where+ f `fmap` Var c = Var (f c)+ _ `fmap` Lit c = Lit c+ f `fmap` CNot c = CNot (fmap f c)+ f `fmap` COr c d = COr (fmap f c) (fmap f d)+ f `fmap` CAnd c d = CAnd (fmap f c) (fmap f d)++instance Foldable Condition where+ f `foldMap` Var c = f c+ _ `foldMap` Lit _ = mempty+ f `foldMap` CNot c = Fold.foldMap f c+ f `foldMap` COr c d = foldMap f c `mappend` foldMap f d+ f `foldMap` CAnd c d = foldMap f c `mappend` foldMap f d++instance Traversable Condition where+ f `traverse` Var c = Var `fmap` f c+ _ `traverse` Lit c = pure $ Lit c+ f `traverse` CNot c = CNot `fmap` Trav.traverse f c+ f `traverse` COr c d = COr `fmap` traverse f c <*> traverse f d+ f `traverse` CAnd c d = CAnd `fmap` traverse f c <*> traverse f d++instance Applicative Condition where+ pure = Var+ (<*>) = ap++instance Monad Condition where+ return = AP.pure+ -- Terminating cases+ (>>=) (Lit x) _ = Lit x+ (>>=) (Var x) f = f x+ -- Recursing cases+ (>>=) (CNot x ) f = CNot (x >>= f)+ (>>=) (COr x y) f = COr (x >>= f) (y >>= f)+ (>>=) (CAnd x y) f = CAnd (x >>= f) (y >>= f)++instance Monoid (Condition a) where+ mempty = Lit False+ mappend = (Semi.<>)++instance Semigroup (Condition a) where+ (<>) = COr++instance Alternative Condition where+ empty = mempty+ (<|>) = mappend++instance MonadPlus Condition where+ mzero = mempty+ mplus = mappend++instance Binary c => Binary (Condition c)+ data CondTree v c a = CondNode { condTreeData :: a , condTreeConstraints :: c@@ -1154,4 +1284,6 @@ , CondTree v c a , Maybe (CondTree v c a))] }- deriving (Show, Eq, Typeable, Data)+ deriving (Show, Eq, Typeable, Data, Generic)++instance (Binary v, Binary c, Binary a) => Binary (CondTree v c a)
Distribution/PackageDescription/Check.hs view
@@ -33,53 +33,35 @@ checkPackageFileNames, ) where -import Data.Maybe- ( isNothing, isJust, catMaybes, maybeToList, fromMaybe )-import Data.List (sort, group, isPrefixOf, nub, find)-import Control.Monad- ( filterM, liftM )-import qualified System.Directory as System- ( doesFileExist, doesDirectoryExist )-import qualified Data.Map as Map- import Distribution.PackageDescription import Distribution.PackageDescription.Configuration- ( flattenPackageDescription, finalizePackageDescription ) import Distribution.Compiler- ( CompilerFlavor(..), buildCompilerFlavor, CompilerId(..)- , unknownCompilerInfo, AbiTag(..) ) import Distribution.System- ( OS(..), Arch(..), buildPlatform ) import Distribution.License- ( License(..), knownLicenses ) import Distribution.Simple.CCompiler- ( filenameCDialect )-import Distribution.Simple.Utils- ( cabalVersion, intercalate, parseFileGlob, FileGlob(..), lowercase )-+import Distribution.Simple.Utils hiding (findPackageDesc, notice) import Distribution.Version- ( Version(..)- , VersionRange(..), foldVersionRange'- , anyVersion, noVersion, thisVersion, laterVersion, earlierVersion- , orLaterVersion, orEarlierVersion- , unionVersionRanges, intersectVersionRanges- , asVersionIntervals, UpperBound(..), isNoVersion ) import Distribution.Package- ( PackageName(PackageName), packageName, packageVersion- , Dependency(..), pkgName )- import Distribution.Text- ( display, disp )+import Language.Haskell.Extension++import Data.Maybe+ ( isNothing, isJust, catMaybes, mapMaybe, maybeToList, fromMaybe )+import Data.List (sort, group, isPrefixOf, nub, find)+import Control.Monad+ ( filterM, liftM )+import qualified System.Directory as System+ ( doesFileExist, doesDirectoryExist )+import qualified Data.Map as Map+ import qualified Text.PrettyPrint as Disp import Text.PrettyPrint ((<>), (<+>)) -import qualified Language.Haskell.Extension as Extension (deprecatedExtensions)-import Language.Haskell.Extension- ( Language(UnknownLanguage), knownLanguages- , Extension(..), KnownExtension(..) )+import qualified System.Directory (getDirectoryContents)+import System.IO (openBinaryFile, IOMode(ReadMode), hGetContents) import System.FilePath ( (</>), takeExtension, isRelative, isAbsolute- , splitDirectories, splitPath )+ , splitDirectories, splitPath, splitExtension ) import System.FilePath.Windows as FilePath.Windows ( isValid ) @@ -108,6 +90,10 @@ -- ban them entirely. | PackageDistSuspicious { explanation :: String } + -- | Like PackageDistSuspicious but will only display warnings+ -- rather than causing abnormal exit when you run 'cabal check'.+ | PackageDistSuspiciousWarn { explanation :: String }+ -- | An issue that is OK in the author's environment but is almost -- certain to be a portability problem for other environments. We can -- quite legitimately refuse to publicly distribute packages with these@@ -128,7 +114,6 @@ | specVersion pkg >= Version specver [] = Nothing | otherwise = check cond pc - -- ------------------------------------------------------------ -- * Standard checks -- ------------------------------------------------------------@@ -150,6 +135,7 @@ checkConfiguredPackage pkg ++ checkConditionals gpkg ++ checkPackageVersions gpkg+ ++ checkDevelopmentOnlyFlags gpkg where pkg = fromMaybe (flattenPackageDescription gpkg) mpkg @@ -184,9 +170,12 @@ , check (null . versionBranch . packageVersion $ pkg) $ PackageBuildImpossible "No 'version' field." - , check (null (executables pkg) && isNothing (library pkg)) $+ , check (all ($ pkg) [ null . executables+ , null . testSuites+ , null . benchmarks+ , isNothing . library ]) $ PackageBuildImpossible- "No executables and no library found. Nothing to do."+ "No executables, libraries, tests, or benchmarks found. Nothing to do." , check (not (null duplicateNames)) $ PackageBuildImpossible $ "Duplicate sections: " ++ commaSep duplicateNames@@ -308,14 +297,6 @@ PackageDistInexcusable $ "The package uses a C/C++/obj-C source file for the 'main-is' field. " ++ "To use this feature you must specify 'cabal-version: >= 1.18'."-- -- Test suites might be built as (internal) libraries named after- -- the test suite and thus their names must not clash with the- -- name of the package.- , check libNameClash $- PackageBuildImpossible $- "The test suite " ++ testName test- ++ " has the same name as the package." ] where moduleDuplicates = dups $ testModules test@@ -328,13 +309,8 @@ TestSuiteExeV10 _ f -> takeExtension f `notElem` [".hs", ".lhs"] _ -> False - libNameClash = testName test `elem` [ libName- | _lib <- maybeToList (library pkg)- , let PackageName libName =- pkgName (package pkg) ]- checkBenchmark :: PackageDescription -> Benchmark -> [PackageCheck]-checkBenchmark pkg bm =+checkBenchmark _pkg bm = catMaybes [ case benchmarkInterface bm of@@ -360,12 +336,6 @@ PackageBuildImpossible $ "The 'main-is' field must specify a '.hs' or '.lhs' file " ++ "(even if it is generated by a preprocessor)."-- -- See comment for similar check on test suites.- , check libNameClash $- PackageBuildImpossible $- "The benchmark " ++ benchmarkName bm- ++ " has the same name as the package." ] where moduleDuplicates = dups $ benchmarkModules bm@@ -374,11 +344,6 @@ BenchmarkExeV10 _ f -> takeExtension f `notElem` [".hs", ".lhs"] _ -> False - libNameClash = benchmarkName bm `elem` [ libName- | _lib <- maybeToList (library pkg)- , let PackageName libName =- pkgName (package pkg) ]- -- ------------------------------------------------------------ -- * Additional pure checks -- ------------------------------------------------------------@@ -407,6 +372,12 @@ ++ commaSep (map display knownBuildTypes) _ -> Nothing + , check (isJust (setupBuildInfo pkg) && buildType pkg /= Just Custom) $+ PackageBuildWarning $+ "Ignoring the 'custom-setup' section because the 'build-type' is "+ ++ "not 'Custom'. Use 'build-type: Custom' if you need to use a "+ ++ "custom Setup.hs script."+ , check (not (null unknownCompilers)) $ PackageBuildWarning $ "Unknown compiler " ++ commaSep (map quote unknownCompilers)@@ -427,14 +398,14 @@ ++ ". Languages must be specified in either the 'default-language' " ++ " or the 'other-languages' field." - , check (not (null deprecatedExtensions)) $+ , check (not (null ourDeprecatedExtensions)) $ PackageDistSuspicious $ "Deprecated extensions: "- ++ commaSep (map (quote . display . fst) deprecatedExtensions)+ ++ commaSep (map (quote . display . fst) ourDeprecatedExtensions) ++ ". " ++ unwords [ "Instead of '" ++ display ext ++ "' use '" ++ display replacement ++ "'."- | (ext, Just replacement) <- deprecatedExtensions ]+ | (ext, Just replacement) <- ourDeprecatedExtensions ] , check (null (category pkg)) $ PackageDistSuspicious "No 'category' field."@@ -476,8 +447,8 @@ unknownExtensions = [ name | bi <- allBuildInfo pkg , UnknownExtension name <- allExtensions bi , name `notElem` map display knownLanguages ]- deprecatedExtensions = nub $ catMaybes- [ find ((==ext) . fst) Extension.deprecatedExtensions+ ourDeprecatedExtensions = nub $ catMaybes+ [ find ((==ext) . fst) deprecatedExtensions | bi <- allBuildInfo pkg , ext <- allExtensions bi ] languagesUsedAsExtensions =@@ -588,19 +559,7 @@ checkGhcOptions pkg = catMaybes [ - check has_WerrorWall $- PackageDistSuspicious $- "'ghc-options: -Wall -Werror' makes the package very easy to "- ++ "break with future GHC versions because new GHC versions often "- ++ "add new warnings. Use just 'ghc-options: -Wall' instead."-- , check (not has_WerrorWall && has_Werror) $- PackageDistSuspicious $- "'ghc-options: -Werror' makes the package easy to "- ++ "break with future GHC versions because new GHC versions often "- ++ "add new warnings."-- , checkFlags ["-fasm"] $+ checkFlags ["-fasm"] $ PackageDistInexcusable $ "'ghc-options: -fasm' is unnecessary and will not work on CPU " ++ "architectures other than x86, x86-64, ppc or sparc."@@ -612,27 +571,16 @@ ++ "is using the FFI incorrectly and will probably not work with GHC " ++ "6.10 or later." - , checkFlags ["-fdefer-type-errors"] $- PackageDistInexcusable $- "'ghc-options: -fdefer-type-errors' is fine during development but "- ++ "is not appropriate for a distributed package."- , checkFlags ["-fhpc"] $ PackageDistInexcusable $- "'ghc-options: -fhpc' is not appropriate for a distributed package."-- -- -dynamic is not a debug flag- , check (any (\opt -> "-d" `isPrefixOf` opt && opt /= "-dynamic")- all_ghc_options) $- PackageDistInexcusable $- "'ghc-options: -d*' debug flags are not appropriate "- ++ "for a distributed package."+ "'ghc-options: -fhpc' is not not necessary. Use the configure flag "+ ++ " --enable-coverage instead." , checkFlags ["-prof"] $ PackageBuildWarning $ "'ghc-options: -prof' is not necessary and will lead to problems " ++ "when used on a library. Use the configure flag "- ++ "--enable-library-profiling and/or --enable-executable-profiling."+ ++ "--enable-library-profiling and/or --enable-profiling." , checkFlags ["-o"] $ PackageBuildWarning $@@ -664,7 +612,7 @@ ++ "Setting it yourself interferes with the --disable-optimization flag." , checkFlags ["-O2"] $- PackageDistSuspicious $+ PackageDistSuspiciousWarn $ "'ghc-options: -O2' is rarely needed. " ++ "Check that it is giving a real benefit " ++ "and not just imposing longer compile times on your users."@@ -687,21 +635,21 @@ "Instead of 'ghc-options: -fglasgow-exts' it is preferable to use " ++ "the 'extensions' field." - , checkProfFlags ["-auto-all"] $- PackageDistSuspicious $- "'ghc-prof-options: -auto-all' is fine during development, but "- ++ "not recommended in a distributed package. "-- , checkProfFlags ["-fprof-auto"] $- PackageDistSuspicious $- "'ghc-prof-options: -fprof-auto' is fine during development, but "- ++ "not recommended in a distributed package. "- , check ("-threaded" `elem` lib_ghc_options) $- PackageDistSuspicious $+ PackageBuildWarning $ "'ghc-options: -threaded' has no effect for libraries. It should " ++ "only be used for executables." + , check ("-rtsopts" `elem` lib_ghc_options) $+ PackageBuildWarning $+ "'ghc-options: -rtsopts' has no effect for libraries. It should "+ ++ "only be used for executables."++ , check (any (\opt -> "-with-rtsopts" `isPrefixOf` opt) lib_ghc_options) $+ PackageBuildWarning $+ "'ghc-options: -with-rtsopts' has no effect for libraries. It "+ ++ "should only be used for executables."+ , checkAlternatives "ghc-options" "extensions" [ (flag, display extension) | flag <- all_ghc_options , Just extension <- [ghcExtension flag] ]@@ -721,26 +669,24 @@ , checkAlternatives "ghc-options" "extra-lib-dirs" [ (flag, dir) | flag@('-':'L':dir) <- all_ghc_options ]- ] - where- has_WerrorWall = flip any ghc_options $ \opts ->- "-Werror" `elem` opts- && ("-Wall" `elem` opts || "-W" `elem` opts)- has_Werror = any (\opts -> "-Werror" `elem` opts) ghc_options+ , checkAlternatives "ghc-options" "frameworks"+ [ (flag, fmwk) | (flag@"-framework", fmwk) <-+ zip all_ghc_options (safeTail all_ghc_options) ] - (ghc_options, ghc_prof_options) =- unzip . map (\bi -> (hcOptions GHC bi, hcProfOptions GHC bi))- $ (allBuildInfo pkg)- all_ghc_options = concat ghc_options- all_ghc_prof_options = concat ghc_prof_options- lib_ghc_options = maybe [] (hcOptions GHC . libBuildInfo) (library pkg)+ , checkAlternatives "ghc-options" "extra-framework-dirs"+ [ (flag, dir) | (flag@"-framework-path", dir) <-+ zip all_ghc_options (safeTail all_ghc_options) ]+ ] - checkFlags,checkProfFlags :: [String] -> PackageCheck -> Maybe PackageCheck- checkFlags flags = doCheckFlags flags all_ghc_options- checkProfFlags flags = doCheckFlags flags all_ghc_prof_options+ where+ all_ghc_options = concatMap get_ghc_options (allBuildInfo pkg)+ lib_ghc_options = maybe [] (get_ghc_options . libBuildInfo) (library pkg)+ get_ghc_options bi = hcOptions GHC bi ++ hcProfOptions GHC bi+ ++ hcSharedOptions GHC bi - doCheckFlags flags opts = check (any (`elem` flags) opts)+ checkFlags :: [String] -> PackageCheck -> Maybe PackageCheck+ checkFlags flags = check (any (`elem` flags) all_ghc_options) ghcExtension ('-':'f':name) = case name of "allow-overlapping-instances" -> enable OverlappingInstances@@ -843,7 +789,7 @@ , isOutsideTree path ] ++ [ PackageDistInexcusable $- quote (kind ++ ": " ++ path) ++ " is an absolute directory."+ quote (kind ++ ": " ++ path) ++ " is an absolute path." | (path, kind) <- relPaths , isAbsolute path ] ++@@ -882,6 +828,7 @@ ++ [ (path, "extra-doc-files") | path <- extraDocFiles pkg ] ++ [ (path, "data-files") | path <- dataFiles pkg ] ++ [ (path, "data-dir") | path <- [dataDir pkg]]+ ++ [ (path, "license-file") | path <- licenseFiles pkg ] ++ concat [ [ (path, "c-sources") | path <- cSources bi ] ++ [ (path, "js-sources") | path <- jsSources bi ]@@ -973,6 +920,13 @@ ++ ". To use this new syntax, the package needs to specify at least" ++ "'cabal-version: >= 1.21'." + -- check use of 'extra-framework-dirs' field+ , checkVersion [1,23] (any (not . null) (buildInfoField extraFrameworkDirs)) $+ -- Just a warning, because this won't break on old Cabal versions.+ PackageDistSuspiciousWarn $+ "To use the 'extra-framework-dirs' field the package needs to specify"+ ++ " at least 'cabal-version: >= 1.23'."+ -- check use of default-extensions field -- don't need to do the equivalent check for other-extensions , checkVersion [1,10] (any (not . null) (buildInfoField defaultExtensions)) $@@ -1084,6 +1038,27 @@ ++ "specify 'cabal-version: >= 1.4'. Alternatively if you require " ++ "compatibility with earlier Cabal versions then you may be able to " ++ "use an equivalent compiler-specific flag."++ , check (specVersion pkg >= Version [1,23] []+ && isNothing (setupBuildInfo pkg)+ && buildType pkg == Just Custom) $+ PackageBuildWarning $+ "Packages using 'cabal-version: >= 1.23' with 'build-type: Custom' "+ ++ "must use a 'custom-setup' section with a 'setup-depends' field "+ ++ "that specifies the dependencies of the Setup.hs script itself. "+ ++ "The 'setup-depends' field uses the same syntax as 'build-depends', "+ ++ "so a simple example would be 'setup-depends: base, Cabal'."++ , check (specVersion pkg < Version [1,23] []+ && isNothing (setupBuildInfo pkg)+ && buildType pkg == Just Custom) $+ PackageDistSuspiciousWarn $+ "From version 1.23 cabal supports specifiying explicit dependencies "+ ++ "for Custom setup scripts. Consider using cabal-version >= 1.23 and "+ ++ "adding a 'custom-setup' section with a 'setup-depends' field "+ ++ "that specifies the dependencies of the Setup.hs script itself. "+ ++ "The 'setup-depends' field uses the same syntax as 'build-depends', "+ ++ "so a simple example would be 'setup-depends: base, Cabal'." ] where -- Perform a check on packages that use a version of the spec less than@@ -1143,14 +1118,13 @@ depsUsingWildcardSyntax = [ dep | dep@(Dependency _ vr) <- buildDepends pkg , usesWildcardSyntax vr ] - -- XXX: If the user writes build-depends: foo with (), this is+ -- TODO: If the user writes build-depends: foo with (), this is -- indistinguishable from build-depends: foo, so there won't be an -- error even though there should be depsUsingThinningRenamingSyntax = [ name | bi <- allBuildInfo pkg- , (name, rns) <- Map.toList (targetBuildRenaming bi)- , rns /= ModuleRenaming True [] ]+ , (name, _) <- Map.toList (targetBuildRenaming bi) ] testedWithUsingWildcardSyntax = [ Dependency (PackageName (display compiler)) vr@@ -1279,7 +1253,7 @@ ++ "new major version of the 'base' package is released. If you are " ++ "not sure what upper bound to use then use the next major " ++ "version. For example if you have tested your package with 'base' "- ++ "version 2 and 3 then use 'build-depends: base >= 2 && < 4'."+ ++ "version 4.5 and 4.6 then use 'build-depends: base >= 4.5 && < 4.7'." ] where@@ -1338,10 +1312,10 @@ unknownOSs = [ os | OS (OtherOS os) <- conditions ] unknownArches = [ arch | Arch (OtherArch arch) <- conditions ] unknownImpls = [ impl | Impl (OtherCompiler impl) _ <- conditions ]- conditions = maybe [] freeVars (condLibrary pkg)- ++ concatMap (freeVars . snd) (condExecutables pkg)- freeVars (CondNode _ _ ifs) = concatMap compfv ifs- compfv (c, ct, mct) = condfv c ++ freeVars ct ++ maybe [] freeVars mct+ conditions = maybe [] fvs (condLibrary pkg)+ ++ concatMap (fvs . snd) (condExecutables pkg)+ fvs (CondNode _ _ ifs) = concatMap compfv ifs -- free variables+ compfv (c, ct, mct) = condfv c ++ fvs ct ++ maybe [] fvs mct condfv c = case c of Var v -> [v] Lit _ -> []@@ -1349,6 +1323,131 @@ COr c1 c2 -> condfv c1 ++ condfv c2 CAnd c1 c2 -> condfv c1 ++ condfv c2 +checkDevelopmentOnlyFlagsBuildInfo :: BuildInfo -> [PackageCheck]+checkDevelopmentOnlyFlagsBuildInfo bi =+ catMaybes [++ check has_WerrorWall $+ PackageDistInexcusable $+ "'ghc-options: -Wall -Werror' makes the package very easy to "+ ++ "break with future GHC versions because new GHC versions often "+ ++ "add new warnings. Use just 'ghc-options: -Wall' instead."+ ++ extraExplanation++ , check (not has_WerrorWall && has_Werror) $+ PackageDistInexcusable $+ "'ghc-options: -Werror' makes the package easy to "+ ++ "break with future GHC versions because new GHC versions often "+ ++ "add new warnings. "+ ++ extraExplanation++ , checkFlags ["-fdefer-type-errors"] $+ PackageDistInexcusable $+ "'ghc-options: -fdefer-type-errors' is fine during development but "+ ++ "is not appropriate for a distributed package. "+ ++ extraExplanation++ -- -dynamic is not a debug flag+ , check (any (\opt -> "-d" `isPrefixOf` opt && opt /= "-dynamic")+ ghc_options) $+ PackageDistInexcusable $+ "'ghc-options: -d*' debug flags are not appropriate "+ ++ "for a distributed package. "+ ++ extraExplanation++ , checkFlags ["-fprof-auto", "-fprof-auto-top", "-fprof-auto-calls",+ "-fprof-cafs", "-fno-prof-count-entries",+ "-auto-all", "-auto", "-caf-all"] $+ PackageDistSuspicious $+ "'ghc-options: -fprof*' profiling flags are typically not "+ ++ "appropriate for a distributed library package. These flags are "+ ++ "useful to profile this package, but when profiling other packages "+ ++ "that use this one these flags clutter the profile output with "+ ++ "excessive detail. If you think other packages really want to see "+ ++ "cost centres from this package then use '-fprof-auto-exported' "+ ++ "which puts cost centres only on exported functions. "+ ++ extraExplanation+ ]+ where+ extraExplanation =+ " Alternatively, if you want to use this, make it conditional based "+ ++ "on a Cabal configuration flag (with 'manual: True' and 'default: "+ ++ "False') and enable that flag during development."++ has_WerrorWall = has_Werror && ( has_Wall || has_W )+ has_Werror = "-Werror" `elem` ghc_options+ has_Wall = "-Wall" `elem` ghc_options+ has_W = "-W" `elem` ghc_options+ ghc_options = hcOptions GHC bi ++ hcProfOptions GHC bi+ ++ hcSharedOptions GHC bi++ checkFlags :: [String] -> PackageCheck -> Maybe PackageCheck+ checkFlags flags = check (any (`elem` flags) ghc_options)++checkDevelopmentOnlyFlags :: GenericPackageDescription -> [PackageCheck]+checkDevelopmentOnlyFlags pkg =+ concatMap checkDevelopmentOnlyFlagsBuildInfo+ [ bi+ | (conditions, bi) <- allConditionalBuildInfo+ , not (any guardedByManualFlag conditions) ]+ where+ guardedByManualFlag = definitelyFalse++ -- We've basically got three-values logic here: True, False or unknown+ -- hence this pattern to propagate the unknown cases properly.+ definitelyFalse (Var (Flag n)) = maybe False not (Map.lookup n manualFlags)+ definitelyFalse (Var _) = False+ definitelyFalse (Lit b) = not b+ definitelyFalse (CNot c) = definitelyTrue c+ definitelyFalse (COr c1 c2) = definitelyFalse c1 && definitelyFalse c2+ definitelyFalse (CAnd c1 c2) = definitelyFalse c1 || definitelyFalse c2++ definitelyTrue (Var (Flag n)) = fromMaybe False (Map.lookup n manualFlags)+ definitelyTrue (Var _) = False+ definitelyTrue (Lit b) = b+ definitelyTrue (CNot c) = definitelyFalse c+ definitelyTrue (COr c1 c2) = definitelyTrue c1 || definitelyTrue c2+ definitelyTrue (CAnd c1 c2) = definitelyTrue c1 && definitelyTrue c2++ manualFlags = Map.fromList+ [ (flagName flag, flagDefault flag)+ | flag <- genPackageFlags pkg+ , flagManual flag ]++ allConditionalBuildInfo :: [([Condition ConfVar], BuildInfo)]+ allConditionalBuildInfo =+ concatMap (collectCondTreePaths libBuildInfo)+ (maybeToList (condLibrary pkg))++ ++ concatMap (collectCondTreePaths buildInfo . snd)+ (condExecutables pkg)++ ++ concatMap (collectCondTreePaths testBuildInfo . snd)+ (condTestSuites pkg)++ ++ concatMap (collectCondTreePaths benchmarkBuildInfo . snd)+ (condBenchmarks pkg)++ -- get all the leaf BuildInfo, paired up with the path (in the tree sense)+ -- of if-conditions that guard it+ collectCondTreePaths :: (a -> b)+ -> CondTree v c a+ -> [([Condition v], b)]+ collectCondTreePaths mapData = go []+ where+ go conditions condNode =+ -- the data at this level in the tree:+ (reverse conditions, mapData (condTreeData condNode))++ : concat+ [ go (condition:conditions) ifThen+ | (condition, ifThen, _) <- condTreeComponents condNode ]++ ++ concat+ [ go (condition:conditions) elseThen+ | (condition, _, Just elseThen) <- condTreeComponents condNode ]++ -- ------------------------------------------------------------ -- * Checks involving files in the package -- ------------------------------------------------------------@@ -1360,8 +1459,10 @@ checkPackageFiles pkg root = checkPackageContent checkFilesIO pkg where checkFilesIO = CheckPackageContentOps {- doesFileExist = System.doesFileExist . relative,- doesDirectoryExist = System.doesDirectoryExist . relative+ doesFileExist = System.doesFileExist . relative,+ doesDirectoryExist = System.doesDirectoryExist . relative,+ getDirectoryContents = System.Directory.getDirectoryContents . relative,+ getFileContents = \f -> openBinaryFile (relative f) ReadMode >>= hGetContents } relative path = root </> path @@ -1369,8 +1470,10 @@ -- Used by 'checkPackageContent'. -- data CheckPackageContentOps m = CheckPackageContentOps {- doesFileExist :: FilePath -> m Bool,- doesDirectoryExist :: FilePath -> m Bool+ doesFileExist :: FilePath -> m Bool,+ doesDirectoryExist :: FilePath -> m Bool,+ getDirectoryContents :: FilePath -> m [FilePath],+ getFileContents :: FilePath -> m String } -- | Sanity check things that requires looking at files in the package.@@ -1384,6 +1487,7 @@ -> PackageDescription -> m [PackageCheck] checkPackageContent ops pkg = do+ cabalBomError <- checkCabalFileBOM ops licenseErrors <- checkLicensesExist ops pkg setupError <- checkSetupExists ops pkg configureError <- checkConfigureExists ops pkg@@ -1391,10 +1495,50 @@ vcsLocation <- checkMissingVcsInfo ops pkg return $ licenseErrors- ++ catMaybes [setupError, configureError]+ ++ catMaybes [cabalBomError, setupError, configureError] ++ localPathErrors ++ vcsLocation +checkCabalFileBOM :: Monad m => CheckPackageContentOps m+ -> m (Maybe PackageCheck)+checkCabalFileBOM ops = do+ epdfile <- findPackageDesc ops+ case epdfile of+ Left pc -> return $ Just pc+ Right pdfile -> (flip check pc . startsWithBOM . fromUTF8) `liftM` (getFileContents ops pdfile)+ where pc = PackageDistInexcusable $+ pdfile ++ " starts with an Unicode byte order mark (BOM). This may cause problems with older cabal versions."++-- |Find a package description file in the given directory. Looks for+-- @.cabal@ files. Like 'Distribution.Simple.Utils.findPackageDesc',+-- but generalized over monads.+findPackageDesc :: Monad m => CheckPackageContentOps m+ -> m (Either PackageCheck FilePath) -- ^<pkgname>.cabal+findPackageDesc ops+ = do let dir = "."+ files <- getDirectoryContents ops dir+ -- to make sure we do not mistake a ~/.cabal/ dir for a <pkgname>.cabal+ -- file we filter to exclude dirs and null base file names:+ cabalFiles <- filterM (doesFileExist ops)+ [ dir </> file+ | file <- files+ , let (name, ext) = splitExtension file+ , not (null name) && ext == ".cabal" ]+ case cabalFiles of+ [] -> return (Left $ PackageBuildImpossible noDesc)+ [cabalFile] -> return (Right cabalFile)+ multiple -> return (Left $ PackageBuildImpossible $ multiDesc multiple)++ where+ noDesc :: String+ noDesc = "No cabal file found.\n"+ ++ "Please create a package description file <pkgname>.cabal"++ multiDesc :: [String] -> String+ multiDesc l = "Multiple cabal files found.\n"+ ++ "Please use only one of: "+ ++ intercalate ", " l+ checkLicensesExist :: Monad m => CheckPackageContentOps m -> PackageDescription -> m [PackageCheck]@@ -1412,10 +1556,11 @@ checkSetupExists :: Monad m => CheckPackageContentOps m -> PackageDescription -> m (Maybe PackageCheck)-checkSetupExists ops _ = do+checkSetupExists ops pkg = do+ let simpleBuild = buildType pkg == Just Simple hsexists <- doesFileExist ops "Setup.hs" lhsexists <- doesFileExist ops "Setup.lhs"- return $ check (not hsexists && not lhsexists) $+ return $ check (not simpleBuild && not hsexists && not lhsexists) $ PackageDistInexcusable $ "The package is missing a Setup.hs or Setup.lhs script." @@ -1438,6 +1583,8 @@ | bi <- allBuildInfo pkg , (dir, kind) <- [ (dir, "extra-lib-dirs") | dir <- extraLibDirs bi ]+ ++ [ (dir, "extra-framework-dirs")+ | dir <- extraFrameworkDirs bi ] ++ [ (dir, "include-dirs") | dir <- includeDirs bi ] ++ [ (dir, "hs-source-dirs") | dir <- hsSourceDirs bi ] , isRelative dir ]@@ -1486,8 +1633,8 @@ -- checkPackageFileNames :: [FilePath] -> [PackageCheck] checkPackageFileNames files =- (take 1 . catMaybes . map checkWindowsPath $ files)- ++ (take 1 . catMaybes . map checkTarPath $ files)+ (take 1 . mapMaybe checkWindowsPath $ files)+ ++ (take 1 . mapMaybe checkTarPath $ files) -- If we get any of these checks triggering then we're likely to get -- many, and that's probably not helpful, so return at most one.
Distribution/PackageDescription/Configuration.hs view
@@ -23,46 +23,38 @@ -- Utils parseCondition, freeVars,+ extractCondition,+ extractConditions,+ addBuildableCondition, mapCondTree, mapTreeData, mapTreeConds, mapTreeConstrs,+ transformAllBuildInfos,+ transformAllBuildDepends, ) where +import Control.Applicative -- 7.10 -Werror workaround.+import Prelude+ import Distribution.Package- ( PackageName, Dependency(..) ) import Distribution.PackageDescription- ( GenericPackageDescription(..), PackageDescription(..)- , Library(..), Executable(..), BuildInfo(..)- , Flag(..), FlagName(..), FlagAssignment- , Benchmark(..), CondTree(..), ConfVar(..), Condition(..)- , TestSuite(..) ) import Distribution.PackageDescription.Utils- ( cabalBug, userBug ) import Distribution.Version- ( VersionRange, anyVersion, intersectVersionRanges, withinRange ) import Distribution.Compiler- ( CompilerId(CompilerId) ) import Distribution.System- ( Platform(..), OS, Arch ) import Distribution.Simple.Utils- ( currentDir, lowercase )-import Distribution.Simple.Compiler- ( CompilerInfo(..) )- import Distribution.Text- ( Text(parse) ) import Distribution.Compat.ReadP as ReadP hiding ( char )-import Control.Arrow (first) import qualified Distribution.Compat.ReadP as ReadP ( char )+import Distribution.Compat.Semigroup as Semi +import Control.Arrow (first) import Data.Char ( isAlphaNum )-import Data.Maybe ( catMaybes, maybeToList )+import Data.Maybe ( mapMaybe, maybeToList ) import Data.Map ( Map, fromListWith, toList ) import qualified Data.Map as Map-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid-#endif+import Data.Tree ( Tree(Node) ) ------------------------------------------------------------------------------ @@ -185,14 +177,14 @@ -- clarity. data DepTestRslt d = DepOk | MissingDeps d -instance Monoid d => Monoid (DepTestRslt d) where+instance Semigroup d => Monoid (DepTestRslt d) where mempty = DepOk- mappend DepOk x = x- mappend x DepOk = x- mappend (MissingDeps d) (MissingDeps d') = MissingDeps (d `mappend` d')-+ mappend = (Semi.<>) -data BT a = BTN a | BTB (BT a) (BT a) -- very simple binary tree+instance Semigroup d => Semigroup (DepTestRslt d) where+ DepOk <> x = x+ x <> DepOk = x+ (MissingDeps d) <> (MissingDeps d') = MissingDeps (d <> d') -- | Try to find a flag assignment that satisfies the constraints of all trees.@@ -201,8 +193,9 @@ -- resulting data, the associated dependencies, and the chosen flag -- assignments. ----- In case of failure, the _smallest_ number of of missing dependencies is--- returned. [TODO: Could also be specified with a function argument.]+-- In case of failure, the union of the dependencies that led to backtracking+-- on all branches is returned.+-- [TODO: Could also be specified with a function argument.] -- -- TODO: The current algorithm is rather naive. A better approach would be to: --@@ -228,65 +221,138 @@ -- ^ Either the missing dependencies (error case), or a pair of -- (set of build targets with dependencies, chosen flag assignments) resolveWithFlags dom os arch impl constrs trees checkDeps =- case try dom [] of- Right r -> Right r- Left dbt -> Left $ findShortest dbt+ either (Left . fromDepMapUnion) Right $ explore (build [] dom) where extraConstrs = toDepMap constrs -- simplify trees by (partially) evaluating all conditions and converting -- dependencies to dependency maps.+ simplifiedTrees :: [CondTree FlagName DependencyMap PDTagged] simplifiedTrees = map ( mapTreeConstrs toDepMap -- convert to maps+ . addBuildableCondition pdTaggedBuildInfo . mapTreeConds (fst . simplifyWithSysParams os arch impl)) trees - -- @try@ recursively tries all possible flag assignments in the domain and- -- either succeeds or returns a binary tree with the missing dependencies- -- encountered in each run. Since the tree is constructed lazily, we- -- avoid some computation overhead in the successful case.- try [] flags =+ -- @explore@ searches a tree of assignments, backtracking whenever a flag+ -- introduces a dependency that cannot be satisfied. If there is no+ -- solution, @explore@ returns the union of all dependencies that caused+ -- it to backtrack. Since the tree is constructed lazily, we avoid some+ -- computation overhead in the successful case.+ explore :: Tree FlagAssignment+ -> Either DepMapUnion (TargetSet PDTagged, FlagAssignment)+ explore (Node flags ts) = let targetSet = TargetSet $ flip map simplifiedTrees $ -- apply additional constraints to all dependencies first (`constrainBy` extraConstrs) . simplifyCondTree (env flags) deps = overallDependencies targetSet in case checkDeps (fromDepMap deps) of- DepOk -> Right (targetSet, flags)- MissingDeps mds -> Left (BTN mds)+ DepOk | null ts -> Right (targetSet, flags)+ | otherwise -> tryAll $ map explore ts+ MissingDeps mds -> Left (toDepMapUnion mds) - try ((n, vals):rest) flags =- tryAll $ map (\v -> try rest ((n, v):flags)) vals+ -- Builds a tree of all possible flag assignments. Internal nodes+ -- have only partial assignments.+ build :: FlagAssignment -> [(FlagName, [Bool])] -> Tree FlagAssignment+ build assigned [] = Node assigned []+ build assigned ((fn, vals) : unassigned) =+ Node assigned $ map (\v -> build ((fn, v) : assigned) unassigned) vals + tryAll :: [Either DepMapUnion a] -> Either DepMapUnion a tryAll = foldr mp mz -- special version of `mplus' for our local purposes- mp (Left xs) (Left ys) = (Left (BTB xs ys))- mp (Left _) m@(Right _) = m+ mp :: Either DepMapUnion a -> Either DepMapUnion a -> Either DepMapUnion a mp m@(Right _) _ = m+ mp _ m@(Right _) = m+ mp (Left xs) (Left ys) =+ let union = Map.foldrWithKey (Map.insertWith' combine)+ (unDepMapUnion xs) (unDepMapUnion ys)+ combine x y = simplifyVersionRange $ unionVersionRanges x y+ in union `seq` Left (DepMapUnion union) -- `mzero'- mz = Left (BTN [])+ mz :: Either DepMapUnion a+ mz = Left (DepMapUnion Map.empty) + env :: FlagAssignment -> FlagName -> Either FlagName Bool env flags flag = (maybe (Left flag) Right . lookup flag) flags - -- for the error case we inspect our lazy tree of missing dependencies and- -- pick the shortest list of missing dependencies- findShortest (BTN x) = x- findShortest (BTB lt rt) =- let l = findShortest lt- r = findShortest rt- in case (l,r) of- ([], xs) -> xs -- [] is too short- (xs, []) -> xs- ([x], _) -> [x] -- single elem is optimum- (_, [x]) -> [x]- (xs, ys) -> if lazyLengthCmp xs ys- then xs else ys- -- lazy variant of @\xs ys -> length xs <= length ys@- lazyLengthCmp [] _ = True- lazyLengthCmp _ [] = False- lazyLengthCmp (_:xs) (_:ys) = lazyLengthCmp xs ys+ pdTaggedBuildInfo :: PDTagged -> BuildInfo+ pdTaggedBuildInfo (Lib l) = libBuildInfo l+ pdTaggedBuildInfo (Exe _ e) = buildInfo e+ pdTaggedBuildInfo (Test _ t) = testBuildInfo t+ pdTaggedBuildInfo (Bench _ b) = benchmarkBuildInfo b+ pdTaggedBuildInfo PDNull = mempty +-- | Transforms a 'CondTree' by putting the input under the "then" branch of a+-- conditional that is True when Buildable is True. If 'addBuildableCondition'+-- can determine that Buildable is always True, it returns the input unchanged.+-- If Buildable is always False, it returns the empty 'CondTree'.+addBuildableCondition :: (Eq v, Monoid a, Monoid c) => (a -> BuildInfo)+ -> CondTree v c a+ -> CondTree v c a+addBuildableCondition getInfo t =+ case extractCondition (buildable . getInfo) t of+ Lit True -> t+ Lit False -> CondNode mempty mempty []+ c -> CondNode mempty mempty [(c, t, Nothing)]++-- Note: extracting buildable conditions.+-- --------------------------------------+--+-- If the conditions in a cond tree lead to Buildable being set to False, then+-- none of the dependencies for this cond tree should actually be taken into+-- account. On the other hand, some of the flags may only be decided in the+-- solver, so we cannot necessarily make the decision whether a component is+-- Buildable or not prior to solving.+--+-- What we are doing here is to partially evaluate a condition tree in order to+-- extract the condition under which Buildable is True. The predicate determines+-- whether data under a 'CondTree' is buildable.+++-- | Extract the condition matched by the given predicate from a cond tree.+--+-- We use this mainly for extracting buildable conditions (see the Note above),+-- but the function is in fact more general.+extractCondition :: Eq v => (a -> Bool) -> CondTree v c a -> Condition v+extractCondition p = go+ where+ go (CondNode x _ cs) | not (p x) = Lit False+ | otherwise = goList cs++ goList [] = Lit True+ goList ((c, t, e) : cs) =+ let+ ct = go t+ ce = maybe (Lit True) go e+ in+ ((c `cAnd` ct) `cOr` (CNot c `cAnd` ce)) `cAnd` goList cs++-- | Extract conditions matched by the given predicate from all cond trees in a+-- 'GenericPackageDescription'.+extractConditions :: (BuildInfo -> Bool) -> GenericPackageDescription+ -> [Condition ConfVar]+extractConditions f gpkg =+ concat [+ maybeToList $ extractCondition (f . libBuildInfo) <$> condLibrary gpkg+ , extractCondition (f . buildInfo) . snd <$> condExecutables gpkg+ , extractCondition (f . testBuildInfo) . snd <$> condTestSuites gpkg+ , extractCondition (f . benchmarkBuildInfo) . snd <$> condBenchmarks gpkg+ ]+++-- | A map of dependencies that combines version ranges using 'unionVersionRanges'.+newtype DepMapUnion = DepMapUnion { unDepMapUnion :: Map PackageName VersionRange }++toDepMapUnion :: [Dependency] -> DepMapUnion+toDepMapUnion ds =+ DepMapUnion $ fromListWith unionVersionRanges [ (p,vr) | Dependency p vr <- ds ]++fromDepMapUnion :: DepMapUnion -> [Dependency]+fromDepMapUnion m = [ Dependency p vr | (p,vr) <- toList (unDepMapUnion m) ]+ -- | A map of dependencies. Newtyped since the default monoid instance is not -- appropriate. The monoid instance uses 'intersectVersionRanges'. newtype DependencyMap = DependencyMap { unDependencyMap :: Map PackageName VersionRange }@@ -294,7 +360,10 @@ instance Monoid DependencyMap where mempty = DependencyMap Map.empty- (DependencyMap a) `mappend` (DependencyMap b) =+ mappend = (Semi.<>)++instance Semigroup DependencyMap where+ (DependencyMap a) <> (DependencyMap b) = DependencyMap (Map.unionWith intersectVersionRanges a b) toDepMap :: [Dependency] -> DependencyMap@@ -304,18 +373,20 @@ fromDepMap :: DependencyMap -> [Dependency] fromDepMap m = [ Dependency p vr | (p,vr) <- toList (unDependencyMap m) ] +-- | Flattens a CondTree using a partial flag assignment. When a condition+-- cannot be evaluated, both branches are ignored. simplifyCondTree :: (Monoid a, Monoid d) => (v -> Either v Bool) -> CondTree v d a -> (d, a) simplifyCondTree env (CondNode a d ifs) =- mconcat $ (d, a) : catMaybes (map simplifyIf ifs)+ mconcat $ (d, a) : mapMaybe simplifyIf ifs where simplifyIf (cnd, t, me) = case simplifyCondition cnd env of (Lit True, _) -> Just $ simplifyCondTree env t (Lit False, _) -> fmap (simplifyCondTree env) me- _ -> error $ "Environment not defined for all free vars"+ _ -> Nothing -- | Flatten a CondTree. This will resolve the CondTree by taking all -- possible paths into account. Note that since branches represent exclusive@@ -350,11 +421,11 @@ where (depss, _) = unzip $ filter (removeDisabledSections . snd) targets removeDisabledSections :: PDTagged -> Bool- removeDisabledSections (Lib _) = True- removeDisabledSections (Exe _ _) = True- removeDisabledSections (Test _ t) = testEnabled t- removeDisabledSections (Bench _ b) = benchmarkEnabled b- removeDisabledSections PDNull = True+ removeDisabledSections (Lib l) = buildable (libBuildInfo l)+ removeDisabledSections (Exe _ e) = buildable (buildInfo e)+ removeDisabledSections (Test _ t) = testEnabled t && buildable (testBuildInfo t)+ removeDisabledSections (Bench _ b) = benchmarkEnabled b && buildable (benchmarkBuildInfo b)+ removeDisabledSections PDNull = True -- Apply extra constraints to a dependency map. -- Combines dependencies where the result will only contain keys from the left@@ -440,14 +511,17 @@ instance Monoid PDTagged where mempty = PDNull- PDNull `mappend` x = x- x `mappend` PDNull = x- Lib l `mappend` Lib l' = Lib (l `mappend` l')- Exe n e `mappend` Exe n' e' | n == n' = Exe n (e `mappend` e')- Test n t `mappend` Test n' t' | n == n' = Test n (t `mappend` t')- Bench n b `mappend` Bench n' b' | n == n' = Bench n (b `mappend` b')- _ `mappend` _ = cabalBug "Cannot combine incompatible tags"+ mappend = (Semi.<>) +instance Semigroup PDTagged where+ PDNull <> x = x+ x <> PDNull = x+ Lib l <> Lib l' = Lib (l <> l')+ Exe n e <> Exe n' e' | n == n' = Exe n (e <> e')+ Test n t <> Test n' t' | n == n' = Test n (t <> t')+ Bench n b <> Bench n' b' | n == n' = Bench n (b <> b')+ _ <> _ = cabalBug "Cannot combine incompatible tags"+ -- | Create a package description with all configurations resolved. -- -- This function takes a `GenericPackageDescription` and several environment@@ -465,9 +539,10 @@ -- -- This function will fail if it cannot find a flag assignment that leads to -- satisfiable dependencies. (It will not try alternative assignments for--- explicitly specified flags.) In case of failure it will return a /minimum/--- number of dependencies that could not be satisfied. On success, it will--- return the package description and the full flag assignment chosen.+-- explicitly specified flags.) In case of failure it will return the missing+-- dependencies that it encountered when trying different flag assignments.+-- On success, it will return the package description and the full flag+-- assignment chosen. -- finalizePackageDescription :: FlagAssignment -- ^ Explicitly specified flag assignments@@ -492,10 +567,6 @@ , testSuites = tests' , benchmarks = bms' , buildDepends = fromDepMap (overallDependencies targetSet)- --TODO: we need to find a way to avoid pulling in deps- -- for non-buildable components. However cannot simply- -- filter at this stage, since if the package were not- -- available we would have failed already. } , flagVals ) @@ -607,3 +678,82 @@ if null (hsSourceDirs bi) then bi { hsSourceDirs = [currentDir] } else bi++-- Walk a 'GenericPackageDescription' and apply @onBuildInfo@/@onSetupBuildInfo@+-- to all nested 'BuildInfo'/'SetupBuildInfo' values.+transformAllBuildInfos :: (BuildInfo -> BuildInfo)+ -> (SetupBuildInfo -> SetupBuildInfo)+ -> GenericPackageDescription+ -> GenericPackageDescription+transformAllBuildInfos onBuildInfo onSetupBuildInfo gpd = gpd'+ where+ onLibrary lib = lib { libBuildInfo = onBuildInfo $ libBuildInfo lib }+ onExecutable exe = exe { buildInfo = onBuildInfo $ buildInfo exe }+ onTestSuite tst = tst { testBuildInfo = onBuildInfo $ testBuildInfo tst }+ onBenchmark bmk = bmk { benchmarkBuildInfo =+ onBuildInfo $ benchmarkBuildInfo bmk }++ pd = packageDescription gpd+ pd' = pd {+ library = fmap onLibrary (library pd),+ executables = map onExecutable (executables pd),+ testSuites = map onTestSuite (testSuites pd),+ benchmarks = map onBenchmark (benchmarks pd),+ setupBuildInfo = fmap onSetupBuildInfo (setupBuildInfo pd)+ }++ gpd' = transformAllCondTrees onLibrary onExecutable+ onTestSuite onBenchmark id+ $ gpd { packageDescription = pd' }++-- | Walk a 'GenericPackageDescription' and apply @f@ to all nested+-- @build-depends@ fields.+transformAllBuildDepends :: (Dependency -> Dependency)+ -> GenericPackageDescription+ -> GenericPackageDescription+transformAllBuildDepends f gpd = gpd'+ where+ onBI bi = bi { targetBuildDepends = map f $ targetBuildDepends bi }+ onSBI stp = stp { setupDepends = map f $ setupDepends stp }+ onPD pd = pd { buildDepends = map f $ buildDepends pd }++ pd' = onPD $ packageDescription gpd+ gpd' = transformAllCondTrees id id id id (map f)+ . transformAllBuildInfos onBI onSBI+ $ gpd { packageDescription = pd' }++-- | Walk all 'CondTree's inside a 'GenericPackageDescription' and apply+-- appropriate transformations to all nodes. Helper function used by+-- 'transformAllBuildDepends' and 'transformAllBuildInfos'.+transformAllCondTrees :: (Library -> Library)+ -> (Executable -> Executable)+ -> (TestSuite -> TestSuite)+ -> (Benchmark -> Benchmark)+ -> ([Dependency] -> [Dependency])+ -> GenericPackageDescription -> GenericPackageDescription+transformAllCondTrees onLibrary onExecutable+ onTestSuite onBenchmark onDepends gpd = gpd'+ where+ gpd' = gpd {+ condLibrary = condLib',+ condExecutables = condExes',+ condTestSuites = condTests',+ condBenchmarks = condBenchs'+ }++ condLib = condLibrary gpd+ condExes = condExecutables gpd+ condTests = condTestSuites gpd+ condBenchs = condBenchmarks gpd++ condLib' = fmap (onCondTree onLibrary) condLib+ condExes' = map (mapSnd $ onCondTree onExecutable) condExes+ condTests' = map (mapSnd $ onCondTree onTestSuite) condTests+ condBenchs' = map (mapSnd $ onCondTree onBenchmark) condBenchs++ mapSnd :: (a -> b) -> (c,a) -> (c,b)+ mapSnd = fmap++ onCondTree :: (a -> b) -> CondTree v [Dependency] a+ -> CondTree v [Dependency] b+ onCondTree g = mapCondTree g onDepends id
Distribution/PackageDescription/Parse.hs view
@@ -41,49 +41,35 @@ flagFieldDescrs ) where -import Data.Char (isSpace)-import Data.Maybe (listToMaybe, isJust)-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid ( Monoid(..) )-#endif-import Data.List (nub, unfoldr, partition, (\\))+import Distribution.ParseUtils hiding (parseFields)+import Distribution.PackageDescription+import Distribution.PackageDescription.Utils+import Distribution.Package+import Distribution.ModuleName+import Distribution.Version+import Distribution.Verbosity+import Distribution.Compiler+import Distribution.PackageDescription.Configuration+import Distribution.Simple.Utils+import Distribution.Text+import Distribution.Compat.ReadP hiding (get)++import Data.Char (isSpace)+import Data.Foldable (traverse_)+import Data.Maybe (listToMaybe, isJust)+import Data.List (nub, unfoldr, partition, (\\)) import Control.Monad (liftM, foldM, when, unless, ap) #if __GLASGOW_HASKELL__ < 710+import Data.Monoid (Monoid(..)) import Control.Applicative (Applicative(..)) #endif-import Control.Arrow (first)+import Control.Arrow (first) import System.Directory (doesFileExist) import qualified Data.ByteString.Lazy.Char8 as BS.Char8-import Data.Typeable-import Data.Data-import qualified Data.Map as Map -import Distribution.Text- ( Text(disp, parse), display, simpleParse )-import Distribution.Compat.ReadP- ((+++), option)-import qualified Distribution.Compat.ReadP as Parse import Text.PrettyPrint -import Distribution.ParseUtils hiding (parseFields)-import Distribution.PackageDescription-import Distribution.PackageDescription.Utils- ( cabalBug, userBug )-import Distribution.Package- ( PackageIdentifier(..), Dependency(..), packageName, packageVersion )-import Distribution.ModuleName ( ModuleName )-import Distribution.Version- ( Version(Version), orLaterVersion- , LowerBound(..), asVersionIntervals )-import Distribution.Verbosity (Verbosity)-import Distribution.Compiler (CompilerFlavor(..))-import Distribution.PackageDescription.Configuration (parseCondition, freeVars)-import Distribution.Simple.Utils- ( die, dieWithLocation, warn, intercalate, lowercase, cabalVersion- , withFileContents, withUTF8FileContents- , writeFileAtomic, writeUTF8File ) - -- ----------------------------------------------------------------------------- -- The PackageDescription type @@ -403,8 +389,7 @@ buildTools (\xs binfo -> binfo{buildTools=xs}) , commaListFieldWithSep vcat "build-depends" disp parse- buildDependsWithRenaming- setBuildDependsWithRenaming+ targetBuildDepends (\xs binfo -> binfo{targetBuildDepends=xs}) , spaceListField "cpp-options" showToken parseTokenQ' cppOptions (\val binfo -> binfo{cppOptions=val})@@ -420,6 +405,9 @@ , listField "frameworks" showToken parseTokenQ frameworks (\val binfo -> binfo{frameworks=val})+ , listField "extra-framework-dirs"+ showToken parseFilePathQ+ extraFrameworkDirs (\val binfo -> binfo{extraFrameworkDirs=val}) , listFieldWithSep vcat "c-sources" showFilePath parseFilePathQ cSources (\paths binfo -> binfo{cSources=paths})@@ -530,6 +518,15 @@ repoSubdir (\val repo -> repo { repoSubdir = val }) ] +------------------------------------------------------------------------------++setupBInfoFieldDescrs :: [FieldDescr SetupBuildInfo]+setupBInfoFieldDescrs =+ [ commaListFieldWithSep vcat "setup-depends"+ disp parse+ setupDepends (\xs binfo -> binfo{setupDepends=xs})+ ]+ -- --------------------------------------------------------------- -- Parsing @@ -589,7 +586,8 @@ -- prop_isMapM fs = mapSimpleFields return fs == return fs --- names of fields that represents dependencies, thus consrca+-- names of fields that represents dependencies+-- TODO: maybe build-tools should go here too? constraintFieldNames :: [String] constraintFieldNames = ["build-depends"] @@ -597,9 +595,9 @@ -- they add and define an accessor that specifies what the dependencies -- are. This way we would completely reuse the parsing knowledge from the -- field descriptor.-parseConstraint :: Field -> ParseResult [DependencyWithRenaming]+parseConstraint :: Field -> ParseResult [Dependency] parseConstraint (F l n v)- | n == "build-depends" = runP l n (parseCommaList parse) v+ | n `elem` constraintFieldNames = runP l n (parseCommaList parse) v parseConstraint f = userBug $ "Constraint was expected (got: " ++ show f ++ ")" {-@@ -627,12 +625,19 @@ instance Functor f => Functor (StT s f) where fmap g (StT f) = StT $ fmap (first g) . f +#if __GLASGOW_HASKELL__ >= 710+instance (Monad m) => Applicative (StT s m) where+#else instance (Monad m, Functor m) => Applicative (StT s m) where- pure = return+#endif+ pure a = StT (\s -> return (a,s)) (<*>) = ap + instance Monad m => Monad (StT s m) where+#if __GLASGOW_HASKELL__ < 710 return a = StT (\s -> return (a,s))+#endif StT f >>= g = StT $ \s -> do (a,s') <- f s runStT (g a) s'@@ -736,13 +741,13 @@ -- 'getBody' assumes that the remaining fields only consist of -- flags, lib and exe sections.- (repos, flags, mlib, exes, tests, bms) <- getBody+ (repos, flags, mcsetup, mlib, exes, tests, bms) <- getBody warnIfRest -- warn if getBody did not parse up to the last field. -- warn about using old/new syntax with wrong cabal-version: maybeWarnCabalVersion (not $ oldSyntax fields0) pkg checkForUndefinedFlags flags mlib exes tests return $ GenericPackageDescription- pkg { sourceRepos = repos }+ pkg { sourceRepos = repos, setupBuildInfo = mcsetup } flags mlib exes tests bms where@@ -848,6 +853,7 @@ -- The body consists of an optional sequence of declarations of flags and -- an arbitrary number of executables and at most one library. getBody :: PM ([SourceRepo], [Flag]+ ,Maybe SetupBuildInfo ,Maybe (CondTree ConfVar [Dependency] Library) ,[(String, CondTree ConfVar [Dependency] Executable)] ,[(String, CondTree ConfVar [Dependency] TestSuite)]@@ -860,8 +866,8 @@ exename <- lift $ runP line_no "executable" parseTokenQ sec_label flds <- collectFields parseExeFields sec_fields skipField- (repos, flags, lib, exes, tests, bms) <- getBody- return (repos, flags, lib, (exename, flds): exes, tests, bms)+ (repos, flags, csetup, lib, exes, tests, bms) <- getBody+ return (repos, flags, csetup, lib, (exename, flds): exes, tests, bms) | sec_type == "test-suite" -> do when (null sec_label) $ lift $ syntaxError line_no@@ -890,7 +896,6 @@ -- Does the current node specify a test type? hasTestType = testInterface ts' /= testInterface emptyTestSuite- components = condTreeComponents ct -- If the current level of the tree specifies a type, -- then we are done. If not, then one of the conditional -- branches below the current node must specify a type.@@ -898,12 +903,13 @@ -- only one need one to specify a type because the -- configure step uses 'mappend' to join together the -- results of flag resolution.- in hasTestType || any checkComponent components+ in hasTestType || any checkComponent (condTreeComponents ct) if checkTestType emptyTestSuite flds then do skipField- (repos, flags, lib, exes, tests, bms) <- getBody- return (repos, flags, lib, exes, (testname, flds) : tests, bms)+ (repos, flags, csetup, lib, exes, tests, bms) <- getBody+ return (repos, flags, csetup, lib, exes,+ (testname, flds) : tests, bms) else lift $ syntaxError line_no $ "Test suite \"" ++ testname ++ "\" is missing required field \"type\" or the field "@@ -938,7 +944,6 @@ -- Does the current node specify a benchmark type? hasBenchmarkType = benchmarkInterface ts' /= benchmarkInterface emptyBenchmark- components = condTreeComponents ct -- If the current level of the tree specifies a type, -- then we are done. If not, then one of the conditional -- branches below the current node must specify a type.@@ -946,12 +951,13 @@ -- only one need one to specify a type because the -- configure step uses 'mappend' to join together the -- results of flag resolution.- in hasBenchmarkType || any checkComponent components+ in hasBenchmarkType || any checkComponent (condTreeComponents ct) if checkBenchmarkType emptyBenchmark flds then do skipField- (repos, flags, lib, exes, tests, bms) <- getBody- return (repos, flags, lib, exes, tests, (benchname, flds) : bms)+ (repos, flags, csetup, lib, exes, tests, bms) <- getBody+ return (repos, flags, csetup, lib, exes,+ tests, (benchname, flds) : bms) else lift $ syntaxError line_no $ "Benchmark \"" ++ benchname ++ "\" is missing required field \"type\" or the field "@@ -964,10 +970,10 @@ syntaxError line_no "'library' expects no argument" flds <- collectFields parseLibFields sec_fields skipField- (repos, flags, lib, exes, tests, bms) <- getBody+ (repos, flags, csetup, lib, exes, tests, bms) <- getBody when (isJust lib) $ lift $ syntaxError line_no "There can only be one library section in a package description."- return (repos, flags, Just flds, exes, tests, bms)+ return (repos, flags, csetup, Just flds, exes, tests, bms) | sec_type == "flag" -> do when (null sec_label) $ lift $@@ -978,8 +984,8 @@ (MkFlag (FlagName (lowercase sec_label)) "" True False) sec_fields skipField- (repos, flags, lib, exes, tests, bms) <- getBody- return (repos, flag:flags, lib, exes, tests, bms)+ (repos, flags, csetup, lib, exes, tests, bms) <- getBody+ return (repos, flag:flags, csetup, lib, exes, tests, bms) | sec_type == "source-repository" -> do when (null sec_label) $ lift $ syntaxError line_no $@@ -1003,9 +1009,23 @@ } sec_fields skipField- (repos, flags, lib, exes, tests, bms) <- getBody- return (repo:repos, flags, lib, exes, tests, bms)+ (repos, flags, csetup, lib, exes, tests, bms) <- getBody+ return (repo:repos, flags, csetup, lib, exes, tests, bms) + | sec_type == "custom-setup" -> do+ unless (null sec_label) $ lift $+ syntaxError line_no "'setup' expects no argument"+ flds <- lift $ parseFields+ setupBInfoFieldDescrs+ warnUnrec+ mempty+ sec_fields+ skipField+ (repos, flags, csetup0, lib, exes, tests, bms) <- getBody+ when (isJust csetup0) $ lift $ syntaxError line_no+ "There can only be one 'custom-setup' section in a package description."+ return (repos, flags, Just flds, lib, exes, tests, bms)+ | otherwise -> do lift $ warning $ "Ignoring unknown section type: " ++ sec_type skipField@@ -1020,7 +1040,7 @@ "If-blocks are not allowed in between stanzas: " ++ show f skipField getBody- Nothing -> return ([], [], Nothing, [], [], [])+ Nothing -> return ([], [], Nothing, Nothing, [], [], []) -- Extracts all fields in a block and returns a 'CondTree'. --@@ -1034,18 +1054,30 @@ condFlds = [ f | f@IfBlock{} <- allflds ] sections = [ s | s@Section{} <- allflds ] - -- Put these through the normal parsing pass too, so that we- -- collect the ModRenamings- let depFlds = filter isConstraint simplFlds- mapM_ (\(Section l n _ _) -> lift . warning $ "Unexpected section '" ++ n ++ "' on line " ++ show l) sections a <- parser simplFlds- deps <- liftM concat . mapM (lift . fmap (map dependency) . parseConstraint) $ depFlds + -- Dependencies must be treated specially: when we+ -- parse into a CondTree, not only do we parse them into+ -- the targetBuildDepends/etc field inside the+ -- PackageDescription, but we also have to put the+ -- combined dependencies into CondTree.+ --+ -- This information is, in principle, redundant, but+ -- putting it here makes it easier for the constraint+ -- solver to pick a flag assignment which supports+ -- all of the dependencies (because it only has+ -- to check the CondTree, rather than grovel everywhere+ -- inside the conditional bits).+ deps <- liftM concat+ . mapM (lift . parseConstraint)+ . filter isConstraint+ $ simplFlds+ ifs <- mapM processIfs condFlds return (CondNode a deps ifs)@@ -1091,7 +1123,7 @@ PM () checkForUndefinedFlags flags mlib exes tests = do let definedFlags = map flagName flags- maybe (return ()) (checkCondTreeFlags definedFlags) mlib+ traverse_ (checkCondTreeFlags definedFlags) mlib mapM_ (checkCondTreeFlags definedFlags . snd) exes mapM_ (checkCondTreeFlags definedFlags . snd) tests @@ -1248,32 +1280,3 @@ --test_findIndentTabs = findIndentTabs $ unlines $ -- [ "foo", " bar", " \t baz", "\t biz\t", "\t\t \t mib" ]---- | Dependencies plus module renamings. This is what users specify; however,--- renaming information is not used for dependency resolution.-data DependencyWithRenaming = DependencyWithRenaming Dependency ModuleRenaming- deriving (Read, Show, Eq, Typeable, Data)--dependency :: DependencyWithRenaming -> Dependency-dependency (DependencyWithRenaming dep _) = dep--instance Text DependencyWithRenaming where- disp (DependencyWithRenaming d rns) = disp d <+> disp rns- parse = do d <- parse- Parse.skipSpaces- rns <- parse- Parse.skipSpaces- return (DependencyWithRenaming d rns)--buildDependsWithRenaming :: BuildInfo -> [DependencyWithRenaming]-buildDependsWithRenaming pkg =- map (\dep@(Dependency n _) ->- DependencyWithRenaming dep- (Map.findWithDefault defaultRenaming n (targetBuildRenaming pkg)))- (targetBuildDepends pkg)--setBuildDependsWithRenaming :: [DependencyWithRenaming] -> BuildInfo -> BuildInfo-setBuildDependsWithRenaming deps pkg = pkg {- targetBuildDepends = map dependency deps,- targetBuildRenaming = Map.fromList (map (\(DependencyWithRenaming (Dependency n _) rns) -> (n, rns)) deps)- }
Distribution/PackageDescription/PrettyPrint.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.PackageDescription.PrettyPrint@@ -18,27 +17,18 @@ showGenericPackageDescription, ) where -#if __GLASGOW_HASKELL__ < 710-import Data.Monoid (Monoid(mempty))-#endif import Distribution.PackageDescription- ( Benchmark(..), BenchmarkInterface(..), benchmarkType- , TestSuite(..), TestSuiteInterface(..), testType- , SourceRepo(..),- customFieldsBI, CondTree(..), Condition(..),- FlagName(..), ConfVar(..), Executable(..), Library(..),- Flag(..), PackageDescription(..),- GenericPackageDescription(..))+import Distribution.Simple.Utils+import Distribution.ParseUtils+import Distribution.PackageDescription.Parse+import Distribution.Package+import Distribution.Text++import Data.Monoid as Mon (Monoid(mempty))+import Data.Maybe (isJust) import Text.PrettyPrint- (hsep, parens, char, nest, empty,- isEmpty, ($$), (<+>), colon, (<>), text, vcat, ($+$), Doc, render)-import Distribution.Simple.Utils (writeUTF8File)-import Distribution.ParseUtils (showFreeText, FieldDescr(..), indentWith, ppField, ppFields)-import Distribution.PackageDescription.Parse (pkgDescrFieldDescrs,binfoFieldDescrs,libFieldDescrs,- sourceRepoFieldDescrs,flagFieldDescrs)-import Distribution.Package (Dependency(..))-import Distribution.Text (Text(..))-import Data.Maybe (isJust, fromJust, isNothing)+ (hsep, parens, char, nest, empty, isEmpty, ($$), (<+>),+ colon, (<>), text, vcat, ($+$), Doc, render) -- | Recompile with false for regression testing simplifiedPrinting :: Bool@@ -226,18 +216,37 @@ else res where -- TODO: this ends up printing trailing spaces when combined with nest.- ppIf (c,thenTree,mElseTree) =- ((emptyLine $ text "if" <+> ppCondition c) $$- nest indentWith (ppCondTree thenTree- (if simplifiedPrinting then (Just it) else Nothing) ppIt))- $+$ (if isNothing mElseTree- then empty- else text "else"- $$ nest indentWith (ppCondTree (fromJust mElseTree)- (if simplifiedPrinting then (Just it) else Nothing) ppIt))+ ppIf (c, thenTree, Just elseTree) = ppIfElse it ppIt c thenTree elseTree+ ppIf (c, thenTree, Nothing) = ppIf' it ppIt c thenTree -emptyLine :: Doc -> Doc-emptyLine d = text "" $+$ d+ppIfCondition :: (Condition ConfVar) -> Doc+ppIfCondition c = (emptyLine $ text "if" <+> ppCondition c) +ppIf' :: a -> (a -> Maybe a -> Doc)+ -> Condition ConfVar+ -> CondTree ConfVar [Dependency] a+ -> Doc+ppIf' it ppIt c thenTree =+ if isEmpty thenDoc+ then Mon.mempty+ else ppIfCondition c $$ nest indentWith thenDoc+ where thenDoc = ppCondTree thenTree (if simplifiedPrinting then (Just it) else Nothing) ppIt +ppIfElse :: a -> (a -> Maybe a -> Doc)+ -> Condition ConfVar+ -> CondTree ConfVar [Dependency] a+ -> CondTree ConfVar [Dependency] a+ -> Doc+ppIfElse it ppIt c thenTree elseTree =+ case (isEmpty thenDoc, isEmpty elseDoc) of+ (True, True) -> Mon.mempty+ (False, True) -> ppIfCondition c $$ nest indentWith thenDoc+ (True, False) -> ppIfCondition (cNot c) $$ nest indentWith elseDoc+ (False, False) -> (ppIfCondition c $$ nest indentWith thenDoc)+ $+$ (text "else" $$ nest indentWith elseDoc)+ where thenDoc = ppCondTree thenTree (if simplifiedPrinting then (Just it) else Nothing) ppIt+ elseDoc = ppCondTree elseTree (if simplifiedPrinting then (Just it) else Nothing) ppIt++emptyLine :: Doc -> Doc+emptyLine d = text "" $+$ d
Distribution/ParseUtils.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.ParseUtils@@ -40,21 +39,17 @@ UnrecFieldParser, warnUnrec, ignoreUnrec, ) where -import Distribution.Compiler (CompilerFlavor, parseCompilerFlavorCompat)+import Distribution.Compiler import Distribution.License import Distribution.Version- ( Version(..), VersionRange, anyVersion )-import Distribution.Package ( PackageName(..), Dependency(..) )-import Distribution.ModuleName (ModuleName)+import Distribution.Package+import Distribution.ModuleName+import qualified Distribution.Compat.MonadFail as Fail import Distribution.Compat.ReadP as ReadP hiding (get) import Distribution.ReadE import Distribution.Text- ( Text(..) ) import Distribution.Simple.Utils- ( comparing, dropWhileEndLE, intercalate, lowercase- , normaliseLineEndings ) import Language.Haskell.Extension- ( Language, Extension ) import Text.PrettyPrint hiding (braces) import Data.Char (isSpace, toLower, isAlphaNum, isDigit)@@ -62,9 +57,7 @@ import Data.Tree as Tree (Tree(..), flatten) import qualified Data.Map as Map import Control.Monad (foldM, ap)-#if __GLASGOW_HASKELL__ < 710-import Control.Applicative (Applicative(..))-#endif+import Control.Applicative as AP (Applicative(..)) import System.FilePath (normalise) import Data.List (sortBy) @@ -98,16 +91,19 @@ fmap f (ParseOk ws x) = ParseOk ws $ f x instance Applicative ParseResult where- pure = return+ pure = ParseOk [] (<*>) = ap instance Monad ParseResult where- return = ParseOk []+ return = AP.pure ParseFailed err >>= _ = ParseFailed err ParseOk ws x >>= f = case f x of ParseFailed err -> ParseFailed err ParseOk ws' x' -> ParseOk (ws'++ws) x'+ fail = Fail.fail++instance Fail.MonadFail ParseResult where fail s = ParseFailed (FromString s Nothing) catchParseError :: ParseResult a -> (PError -> ParseResult a)@@ -660,8 +656,7 @@ parseOptVersion :: ReadP r Version parseOptVersion = parseQuoted ver <++ ver where ver :: ReadP r Version- ver = parse <++ return noVersion- noVersion = Version [] []+ ver = parse <++ return (Version [] []) parseTestedWithQ :: ReadP r (CompilerFlavor,VersionRange) parseTestedWithQ = parseQuoted tw <++ tw
Distribution/Simple.hs view
@@ -56,63 +56,48 @@ -- local import Distribution.Simple.Compiler hiding (Flag) import Distribution.Simple.UserHooks-import Distribution.Package --must not specify imports, since we're exporting module.-import Distribution.PackageDescription- ( PackageDescription(..), GenericPackageDescription, Executable(..)- , updatePackageDescription, hasLibs- , HookedBuildInfo, emptyHookedBuildInfo )+import Distribution.Package+import Distribution.PackageDescription hiding (Flag) import Distribution.PackageDescription.Parse- ( readPackageDescription, readHookedBuildInfo ) import Distribution.PackageDescription.Configuration- ( flattenPackageDescription ) import Distribution.Simple.Program- ( defaultProgramConfiguration, addKnownPrograms, builtinPrograms- , restoreProgramConfiguration, reconfigurePrograms )-import Distribution.Simple.PreProcess (knownSuffixHandlers, PPSuffixHandler)+import Distribution.Simple.Program.Db+import Distribution.Simple.PreProcess import Distribution.Simple.Setup import Distribution.Simple.Command -import Distribution.Simple.Build ( build, repl )-import Distribution.Simple.SrcDist ( sdist )+import Distribution.Simple.Build+import Distribution.Simple.SrcDist import Distribution.Simple.Register- ( register, unregister ) import Distribution.Simple.Configure- ( getPersistBuildConfig, maybeGetPersistBuildConfig- , writePersistBuildConfig, checkPersistBuildConfigOutdated- , configure, checkForeignDeps ) -import Distribution.Simple.LocalBuildInfo ( LocalBuildInfo(..) )-import Distribution.Simple.Bench (bench)-import Distribution.Simple.BuildPaths ( srcPref)-import Distribution.Simple.Test (test)-import Distribution.Simple.Install (install)-import Distribution.Simple.Haddock (haddock, hscolour)+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.Bench+import Distribution.Simple.BuildPaths+import Distribution.Simple.Test+import Distribution.Simple.Install+import Distribution.Simple.Haddock import Distribution.Simple.Utils- (die, notice, info, warn, setupMessage, chattyTry,- defaultPackageDesc, defaultHookedPackageDesc,- rawSystemExitWithEnv, cabalVersion, topHandler )-import Distribution.System- ( OS(..), buildOS )+import Distribution.Utils.NubList import Distribution.Verbosity import Language.Haskell.Extension import Distribution.Version import Distribution.License import Distribution.Text- ( display ) -- Base-import System.Environment(getArgs, getProgName)-import System.Directory(removeFile, doesFileExist,- doesDirectoryExist, removeDirectoryRecursive)-import System.Exit (exitWith,ExitCode(..))-import System.IO.Error (isDoesNotExistError)-import Control.Exception (throwIO)-import Distribution.Compat.Environment (getEnvironment)-import Distribution.Compat.Exception (catchIO)+import System.Environment (getArgs, getProgName)+import System.Directory (removeFile, doesFileExist+ ,doesDirectoryExist, removeDirectoryRecursive)+import System.Exit (exitWith,ExitCode(..))+import System.FilePath (searchPathSeparator)+import Distribution.Compat.Environment (getEnvironment)+import Distribution.Compat.GetShortPathName (getShortPathName) import Control.Monad (when)-import Data.List (intercalate, unionBy, nub, (\\))+import Data.Foldable (traverse_)+import Data.List (unionBy, nub, (\\)) -- | A simple implementation of @main@ for a Cabal setup script. -- It reads the package description file using IO, and performs the@@ -196,151 +181,166 @@ configureAction :: UserHooks -> ConfigFlags -> Args -> IO LocalBuildInfo configureAction hooks flags args = do- let distPref = fromFlag $ configDistPref flags- pbi <- preConf hooks args flags+ distPref <- findDistPrefOrDefault (configDistPref flags)+ let flags' = flags { configDistPref = toFlag distPref }+ pbi <- preConf hooks args flags' - (mb_pd_file, pkg_descr0) <- confPkgDescr+ (mb_pd_file, pkg_descr0) <- confPkgDescr - -- get_pkg_descr (configVerbosity flags')- --let pkg_descr = updatePackageDescription pbi pkg_descr0- let epkg_descr = (pkg_descr0, pbi)+ --get_pkg_descr (configVerbosity flags')+ --let pkg_descr = updatePackageDescription pbi pkg_descr0+ let epkg_descr = (pkg_descr0, pbi) - --(warns, ers) <- sanityCheckPackage pkg_descr- --errorOut (configVerbosity flags') warns ers+ --(warns, ers) <- sanityCheckPackage pkg_descr+ --errorOut (configVerbosity flags') warns ers - localbuildinfo0 <- confHook hooks epkg_descr flags+ localbuildinfo0 <- confHook hooks epkg_descr flags' - -- remember the .cabal filename if we know it- -- and all the extra command line args- let localbuildinfo = localbuildinfo0 {- pkgDescrFile = mb_pd_file,- extraConfigArgs = args- }- writePersistBuildConfig distPref localbuildinfo+ -- remember the .cabal filename if we know it+ -- and all the extra command line args+ let localbuildinfo = localbuildinfo0 {+ pkgDescrFile = mb_pd_file,+ extraConfigArgs = args+ }+ writePersistBuildConfig distPref localbuildinfo - let pkg_descr = localPkgDescr localbuildinfo- postConf hooks args flags pkg_descr localbuildinfo- return localbuildinfo- where- verbosity = fromFlag (configVerbosity flags)- confPkgDescr :: IO (Maybe FilePath, GenericPackageDescription)- confPkgDescr = do- mdescr <- readDesc hooks- case mdescr of- Just descr -> return (Nothing, descr)- Nothing -> do- pdfile <- defaultPackageDesc verbosity- descr <- readPackageDescription verbosity pdfile- return (Just pdfile, descr)+ let pkg_descr = localPkgDescr localbuildinfo+ postConf hooks args flags' pkg_descr localbuildinfo+ return localbuildinfo+ where+ verbosity = fromFlag (configVerbosity flags)+ confPkgDescr :: IO (Maybe FilePath, GenericPackageDescription)+ confPkgDescr = do+ mdescr <- readDesc hooks+ case mdescr of+ Just descr -> return (Nothing, descr)+ Nothing -> do+ pdfile <- defaultPackageDesc verbosity+ descr <- readPackageDescription verbosity pdfile+ return (Just pdfile, descr) buildAction :: UserHooks -> BuildFlags -> Args -> IO () buildAction hooks flags args = do- let distPref = fromFlag $ buildDistPref flags- verbosity = fromFlag $ buildVerbosity flags+ distPref <- findDistPrefOrDefault (buildDistPref flags)+ let verbosity = fromFlag $ buildVerbosity flags+ flags' = flags { buildDistPref = toFlag distPref } lbi <- getBuildConfig hooks verbosity distPref progs <- reconfigurePrograms verbosity- (buildProgramPaths flags)- (buildProgramArgs flags)+ (buildProgramPaths flags')+ (buildProgramArgs flags') (withPrograms lbi) hookedAction preBuild buildHook postBuild (return lbi { withPrograms = progs })- hooks flags { buildArgs = args } args+ hooks flags' { buildArgs = args } args replAction :: UserHooks -> ReplFlags -> Args -> IO () replAction hooks flags args = do- let distPref = fromFlag $ replDistPref flags- verbosity = fromFlag $ replVerbosity flags+ distPref <- findDistPrefOrDefault (replDistPref flags)+ let verbosity = fromFlag $ replVerbosity flags+ flags' = flags { replDistPref = toFlag distPref } lbi <- getBuildConfig hooks verbosity distPref progs <- reconfigurePrograms verbosity- (replProgramPaths flags)- (replProgramArgs flags)+ (replProgramPaths flags')+ (replProgramArgs flags') (withPrograms lbi) - pbi <- preRepl hooks args flags+ pbi <- preRepl hooks args flags' let lbi' = lbi { withPrograms = progs } pkg_descr0 = localPkgDescr lbi' pkg_descr = updatePackageDescription pbi pkg_descr0- replHook hooks pkg_descr lbi' hooks flags args- postRepl hooks args flags pkg_descr lbi'+ replHook hooks pkg_descr lbi' hooks flags' args+ postRepl hooks args flags' pkg_descr lbi' hscolourAction :: UserHooks -> HscolourFlags -> Args -> IO ()-hscolourAction hooks flags args- = do let distPref = fromFlag $ hscolourDistPref flags- verbosity = fromFlag $ hscolourVerbosity flags- hookedAction preHscolour hscolourHook postHscolour- (getBuildConfig hooks verbosity distPref)- hooks flags args+hscolourAction hooks flags args = do+ distPref <- findDistPrefOrDefault (hscolourDistPref flags)+ let verbosity = fromFlag $ hscolourVerbosity flags+ flags' = flags { hscolourDistPref = toFlag distPref }+ hookedAction preHscolour hscolourHook postHscolour+ (getBuildConfig hooks verbosity distPref)+ hooks flags' args haddockAction :: UserHooks -> HaddockFlags -> Args -> IO () haddockAction hooks flags args = do- let distPref = fromFlag $ haddockDistPref flags- verbosity = fromFlag $ haddockVerbosity flags+ distPref <- findDistPrefOrDefault (haddockDistPref flags)+ let verbosity = fromFlag $ haddockVerbosity flags+ flags' = flags { haddockDistPref = toFlag distPref } lbi <- getBuildConfig hooks verbosity distPref progs <- reconfigurePrograms verbosity- (haddockProgramPaths flags)- (haddockProgramArgs flags)+ (haddockProgramPaths flags')+ (haddockProgramArgs flags') (withPrograms lbi) hookedAction preHaddock haddockHook postHaddock (return lbi { withPrograms = progs })- hooks flags args+ hooks flags' args cleanAction :: UserHooks -> CleanFlags -> Args -> IO () cleanAction hooks flags args = do- pbi <- preClean hooks args flags+ distPref <- findDistPrefOrDefault (cleanDistPref flags)+ let flags' = flags { cleanDistPref = toFlag distPref } - pdfile <- defaultPackageDesc verbosity- ppd <- readPackageDescription verbosity pdfile- let pkg_descr0 = flattenPackageDescription ppd- -- We don't sanity check for clean as an error- -- here would prevent cleaning:- --sanityCheckHookedBuildInfo pkg_descr0 pbi- let pkg_descr = updatePackageDescription pbi pkg_descr0+ pbi <- preClean hooks args flags' - cleanHook hooks pkg_descr () hooks flags- postClean hooks args flags pkg_descr ()- where verbosity = fromFlag (cleanVerbosity flags)+ pdfile <- defaultPackageDesc verbosity+ ppd <- readPackageDescription verbosity pdfile+ let pkg_descr0 = flattenPackageDescription ppd+ -- We don't sanity check for clean as an error+ -- here would prevent cleaning:+ --sanityCheckHookedBuildInfo pkg_descr0 pbi+ let pkg_descr = updatePackageDescription pbi pkg_descr0 + cleanHook hooks pkg_descr () hooks flags'+ postClean hooks args flags' pkg_descr ()+ where+ verbosity = fromFlag (cleanVerbosity flags)+ copyAction :: UserHooks -> CopyFlags -> Args -> IO ()-copyAction hooks flags args- = do let distPref = fromFlag $ copyDistPref flags- verbosity = fromFlag $ copyVerbosity flags- hookedAction preCopy copyHook postCopy- (getBuildConfig hooks verbosity distPref)- hooks flags args+copyAction hooks flags args = do+ distPref <- findDistPrefOrDefault (copyDistPref flags)+ let verbosity = fromFlag $ copyVerbosity flags+ flags' = flags { copyDistPref = toFlag distPref }+ hookedAction preCopy copyHook postCopy+ (getBuildConfig hooks verbosity distPref)+ hooks flags' args installAction :: UserHooks -> InstallFlags -> Args -> IO ()-installAction hooks flags args- = do let distPref = fromFlag $ installDistPref flags- verbosity = fromFlag $ installVerbosity flags- hookedAction preInst instHook postInst- (getBuildConfig hooks verbosity distPref)- hooks flags args+installAction hooks flags args = do+ distPref <- findDistPrefOrDefault (installDistPref flags)+ let verbosity = fromFlag $ installVerbosity flags+ flags' = flags { installDistPref = toFlag distPref }+ hookedAction preInst instHook postInst+ (getBuildConfig hooks verbosity distPref)+ hooks flags' args sdistAction :: UserHooks -> SDistFlags -> Args -> IO () sdistAction hooks flags args = do- let distPref = fromFlag $ sDistDistPref flags- pbi <- preSDist hooks args flags+ distPref <- findDistPrefOrDefault (sDistDistPref flags)+ let flags' = flags { sDistDistPref = toFlag distPref }+ pbi <- preSDist hooks args flags' - mlbi <- maybeGetPersistBuildConfig distPref- pdfile <- defaultPackageDesc verbosity- ppd <- readPackageDescription verbosity pdfile- let pkg_descr0 = flattenPackageDescription ppd- sanityCheckHookedBuildInfo pkg_descr0 pbi- let pkg_descr = updatePackageDescription pbi pkg_descr0+ mlbi <- maybeGetPersistBuildConfig distPref+ pdfile <- defaultPackageDesc verbosity+ ppd <- readPackageDescription verbosity pdfile+ let pkg_descr0 = flattenPackageDescription ppd+ sanityCheckHookedBuildInfo pkg_descr0 pbi+ let pkg_descr = updatePackageDescription pbi pkg_descr0 - sDistHook hooks pkg_descr mlbi hooks flags- postSDist hooks args flags pkg_descr mlbi- where verbosity = fromFlag (sDistVerbosity flags)+ sDistHook hooks pkg_descr mlbi hooks flags'+ postSDist hooks args flags' pkg_descr mlbi+ where+ verbosity = fromFlag (sDistVerbosity flags) testAction :: UserHooks -> TestFlags -> Args -> IO () testAction hooks flags args = do- let distPref = fromFlag $ testDistPref flags- verbosity = fromFlag $ testVerbosity flags+ distPref <- findDistPrefOrDefault (testDistPref flags)+ let verbosity = fromFlag $ testVerbosity flags+ flags' = flags { testDistPref = toFlag distPref }+ localBuildInfo <- getBuildConfig hooks verbosity distPref let pkg_descr = localPkgDescr localBuildInfo -- It is safe to do 'runTests' before the new test handler because the@@ -349,31 +349,34 @@ runTests hooks args False pkg_descr localBuildInfo hookedActionWithArgs preTest testHook postTest (getBuildConfig hooks verbosity distPref)- hooks flags args+ hooks flags' args benchAction :: UserHooks -> BenchmarkFlags -> Args -> IO () benchAction hooks flags args = do- let distPref = fromFlag $ benchmarkDistPref flags- verbosity = fromFlag $ benchmarkVerbosity flags+ distPref <- findDistPrefOrDefault (benchmarkDistPref flags)+ let verbosity = fromFlag $ benchmarkVerbosity flags+ flags' = flags { benchmarkDistPref = toFlag distPref } hookedActionWithArgs preBench benchHook postBench (getBuildConfig hooks verbosity distPref)- hooks flags args+ hooks flags' args registerAction :: UserHooks -> RegisterFlags -> Args -> IO ()-registerAction hooks flags args- = do let distPref = fromFlag $ regDistPref flags- verbosity = fromFlag $ regVerbosity flags- hookedAction preReg regHook postReg- (getBuildConfig hooks verbosity distPref)- hooks flags args+registerAction hooks flags args = do+ distPref <- findDistPrefOrDefault (regDistPref flags)+ let verbosity = fromFlag $ regVerbosity flags+ flags' = flags { regDistPref = toFlag distPref }+ hookedAction preReg regHook postReg+ (getBuildConfig hooks verbosity distPref)+ hooks flags' args unregisterAction :: UserHooks -> RegisterFlags -> Args -> IO ()-unregisterAction hooks flags args- = do let distPref = fromFlag $ regDistPref flags- verbosity = fromFlag $ regVerbosity flags- hookedAction preUnreg unregHook postUnreg- (getBuildConfig hooks verbosity distPref)- hooks flags args+unregisterAction hooks flags args = do+ distPref <- findDistPrefOrDefault (regDistPref flags)+ let verbosity = fromFlag $ regVerbosity flags+ flags' = flags { regDistPref = toFlag distPref }+ hookedAction preUnreg unregHook postUnreg+ (getBuildConfig hooks verbosity distPref)+ hooks flags' args hookedAction :: (UserHooks -> Args -> flags -> IO HookedBuildInfo) -> (UserHooks -> PackageDescription -> LocalBuildInfo@@ -451,9 +454,9 @@ -- Since the list of unconfigured programs is not serialized, -- restore it to the same value as normally used at the beginning -- of a configure run:- configPrograms = restoreProgramConfiguration+ configPrograms_ = restoreProgramConfiguration (builtinPrograms ++ hookedPrograms hooks)- (configPrograms cFlags),+ `fmap` configPrograms_ cFlags, -- Use the current, not saved verbosity level: configVerbosity = Flag verbosity@@ -466,7 +469,7 @@ clean :: PackageDescription -> CleanFlags -> IO () clean pkg_descr flags = do- let distPref = fromFlag $ cleanDistPref flags+ let distPref = fromFlagOrDefault defaultDistPref $ cleanDistPref flags notice verbosity "cleaning..." maybeConfig <- if fromFlag (cleanSaveConf flags)@@ -483,7 +486,7 @@ mapM_ removeFileOrDirectory (extraTmpFiles pkg_descr) -- If the user wanted to save the config, write it back- maybe (return ()) (writePersistBuildConfig distPref) maybeConfig+ traverse_ (writePersistBuildConfig distPref) maybeConfig where removeFileOrDirectory :: FilePath -> IO ()@@ -607,42 +610,35 @@ runConfigureScript :: Verbosity -> Bool -> ConfigFlags -> LocalBuildInfo -> IO () runConfigureScript verbosity backwardsCompatHack flags lbi = do- env <- getEnvironment let programConfig = withPrograms lbi (ccProg, ccFlags) <- configureCCompiler verbosity programConfig+ ccProgShort <- getShortPathName ccProg -- The C compiler's compilation and linker flags (e.g. -- "C compiler flags" and "Gcc Linker flags" from GHC) have already -- been merged into ccFlags, so we set both CFLAGS and LDFLAGS -- to ccFlags -- We don't try and tell configure which ld to use, as we don't have -- a way to pass its flags too- let env' = appendToEnvironment ("CFLAGS", unwords ccFlags)- env- args' = args ++ ["--with-gcc=" ++ ccProg]- handleNoWindowsSH $- rawSystemExitWithEnv verbosity "sh" args' env'+ let extraPath = fromNubList $ configProgramPathExtra flags+ let cflagsEnv = maybe (unwords ccFlags) (++ (" " ++ unwords ccFlags)) $ lookup "CFLAGS" env+ spSep = [searchPathSeparator]+ pathEnv = maybe (intercalate spSep extraPath) ((intercalate spSep extraPath ++ spSep)++) $ lookup "PATH" env+ overEnv = ("CFLAGS", Just cflagsEnv) : [("PATH", Just pathEnv) | not (null extraPath)]+ args' = args ++ ["CC=" ++ ccProgShort]+ shProg = simpleProgram "sh"+ progDb = modifyProgramSearchPath (\p -> map ProgramSearchPathDir extraPath ++ p) emptyProgramDb+ shConfiguredProg <- lookupProgram shProg `fmap` configureProgram verbosity shProg progDb+ case shConfiguredProg of+ Just sh -> runProgramInvocation verbosity (programInvocation (sh {programOverrideEnv = overEnv}) args')+ Nothing -> die notFoundMsg where args = "./configure" : configureArgs backwardsCompatHack flags - appendToEnvironment (key, val) [] = [(key, val)]- appendToEnvironment (key, val) (kv@(k, v) : rest)- | key == k = (key, v ++ " " ++ val) : rest- | otherwise = kv : appendToEnvironment (key, val) rest-- handleNoWindowsSH action- | buildOS /= Windows- = action-- | otherwise- = action- `catchIO` \ioe -> if isDoesNotExistError ioe- then die notFoundMsg- else throwIO ioe-- notFoundMsg = "The package has a './configure' script. This requires a "- ++ "Unix compatibility toolchain such as MinGW+MSYS or Cygwin."+ notFoundMsg = "The package has a './configure' script. If you are on Windows, This requires a "+ ++ "Unix compatibility toolchain such as MinGW+MSYS or Cygwin. "+ ++ "If you are not on Windows, ensure that an 'sh' command is discoverable in your path." getHookedBuildInfo :: Verbosity -> IO HookedBuildInfo getHookedBuildInfo verbosity = do@@ -695,6 +691,5 @@ defaultRegHook pkg_descr localbuildinfo _ flags = if hasLibs pkg_descr then register pkg_descr localbuildinfo flags- else setupMessage verbosity+ else setupMessage (fromFlag (regVerbosity flags)) "Package contains no library to register:" (packageId pkg_descr)- where verbosity = fromFlag (regVerbosity flags)
Distribution/Simple/Bench.hs view
@@ -16,22 +16,17 @@ ) where import qualified Distribution.PackageDescription as PD- ( PackageDescription(..), BuildInfo(buildable)- , Benchmark(..), BenchmarkInterface(..), benchmarkType, hasBenchmarks )-import Distribution.Simple.BuildPaths ( exeExtension )-import Distribution.Simple.Compiler ( compilerInfo )+import Distribution.Simple.BuildPaths+import Distribution.Simple.Compiler import Distribution.Simple.InstallDirs- ( fromPathTemplate, initialPathTemplateEnv, PathTemplateVariable(..)- , substPathTemplate , toPathTemplate, PathTemplate ) import qualified Distribution.Simple.LocalBuildInfo as LBI- ( LocalBuildInfo(..) )-import Distribution.Simple.Setup ( BenchmarkFlags(..), fromFlag )-import Distribution.Simple.UserHooks ( Args )-import Distribution.Simple.Utils ( die, notice, rawSystemExitCode )+import Distribution.Simple.Setup+import Distribution.Simple.UserHooks+import Distribution.Simple.Utils import Distribution.Text -import Control.Monad ( when, unless )-import System.Exit ( ExitCode(..), exitFailure, exitWith )+import Control.Monad ( when, unless, forM )+import System.Exit ( ExitCode(..), exitFailure, exitSuccess ) import System.Directory ( doesFileExist ) import System.FilePath ( (</>), (<.>) ) @@ -78,9 +73,9 @@ ++ show (disp $ PD.benchmarkType bm) exitFailure - when (not $ PD.hasBenchmarks pkg_descr) $ do+ unless (PD.hasBenchmarks pkg_descr) $ do notice verbosity "Package has no benchmarks."- exitWith ExitSuccess+ exitSuccess when (PD.hasBenchmarks pkg_descr && null enabledBenchmarks) $ die $ "No benchmarks enabled. Did you remember to configure with "@@ -88,7 +83,7 @@ bmsToRun <- case benchmarkNames of [] -> return enabledBenchmarks- names -> flip mapM names $ \bmName ->+ names -> forM names $ \bmName -> let benchmarkMap = zip enabledNames enabledBenchmarks enabledNames = map PD.benchmarkName enabledBenchmarks allNames = map PD.benchmarkName pkgBenchmarks@@ -123,6 +118,6 @@ fromPathTemplate $ substPathTemplate env template where env = initialPathTemplateEnv- (PD.package pkg_descr) (LBI.pkgKey lbi)+ (PD.package pkg_descr) (LBI.localUnitId lbi) (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) ++ [(BenchmarkNameVar, toPathTemplate $ PD.benchmarkName bm)]
Distribution/Simple/Build.hs view
@@ -23,6 +23,7 @@ writeAutogenFiles, ) where +import Distribution.Package import qualified Distribution.Simple.GHC as GHC import qualified Distribution.Simple.GHCJS as GHCJS import qualified Distribution.Simple.JHC as JHC@@ -33,65 +34,40 @@ import qualified Distribution.Simple.Build.Macros as Build.Macros import qualified Distribution.Simple.Build.PathsModule as Build.PathsModule -import Distribution.Package- ( Package(..), PackageName(..), PackageIdentifier(..)- , Dependency(..), thisPackageVersion, mkPackageKey, packageName )-import Distribution.Simple.Compiler- ( Compiler, CompilerFlavor(..), compilerFlavor- , PackageDB(..), PackageDBStack, packageKeySupported )-import Distribution.PackageDescription- ( PackageDescription(..), BuildInfo(..), Library(..), Executable(..)- , TestSuite(..), TestSuiteInterface(..), Benchmark(..)- , BenchmarkInterface(..), defaultRenaming )+import Distribution.Simple.Compiler hiding (Flag)+import Distribution.PackageDescription hiding (Flag) import qualified Distribution.InstalledPackageInfo as IPI import qualified Distribution.ModuleName as ModuleName import Distribution.ModuleName (ModuleName) import Distribution.Simple.Setup- ( Flag(..), BuildFlags(..), ReplFlags(..), fromFlag ) import Distribution.Simple.BuildTarget- ( BuildTarget(..), readBuildTargets ) import Distribution.Simple.PreProcess- ( preprocessComponent, PPSuffixHandler ) import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(compiler, buildDir, withPackageDB, withPrograms, pkgKey)- , Component(..), componentName, getComponent, componentBuildInfo- , ComponentLocalBuildInfo(..), pkgEnabledComponents- , withComponentsInBuildOrder, componentsInBuildOrder- , ComponentName(..), showComponentName- , ComponentDisabledReason(..), componentDisabledReason- , inplacePackageId, LibraryName(..) ) import Distribution.Simple.Program.Types import Distribution.Simple.Program.Db-import qualified Distribution.Simple.Program.HcPkg as HcPkg import Distribution.Simple.BuildPaths- ( autogenModulesDir, autogenModuleName, cppHeaderName, exeExtension )+import Distribution.Simple.Configure import Distribution.Simple.Register- ( registerPackage, inplaceInstalledPackageInfo )-import Distribution.Simple.Test.LibV09 ( stubFilePath, stubName )+import Distribution.Simple.Test.LibV09 import Distribution.Simple.Utils- ( createDirectoryIfMissingVerbose, rewriteFile- , die, info, debug, warn, setupMessage ) -import Distribution.Verbosity- ( Verbosity )+import Distribution.System import Distribution.Text- ( display )+import Distribution.Verbosity import qualified Data.Map as Map-import Data.Maybe- ( maybeToList )+import qualified Data.Set as Set import Data.Either ( partitionEithers ) import Data.List- ( intersect, intercalate )+ ( intersect ) import Control.Monad ( when, unless, forM_ ) import System.FilePath ( (</>), (<.>) ) import System.Directory- ( getCurrentDirectory, removeDirectoryRecursive, removeFile- , doesDirectoryExist, doesFileExist )+ ( getCurrentDirectory ) -- ----------------------------------------------------------------------------- -- |Build the libraries and executables in this package.@@ -178,11 +154,12 @@ -- | Start an interpreter without loading any package files.-startInterpreter :: Verbosity -> ProgramDb -> Compiler -> PackageDBStack -> IO ()-startInterpreter verbosity programDb comp packageDBs =+startInterpreter :: Verbosity -> ProgramDb -> Compiler -> Platform+ -> PackageDBStack -> IO ()+startInterpreter verbosity programDb comp platform packageDBs = case compilerFlavor comp of- GHC -> GHC.startInterpreter verbosity programDb comp packageDBs- GHCJS -> GHCJS.startInterpreter verbosity programDb comp packageDBs+ GHC -> GHC.startInterpreter verbosity programDb comp platform packageDBs+ GHCJS -> GHCJS.startInterpreter verbosity programDb comp platform packageDBs _ -> die "A REPL is not supported with this compiler." buildComponent :: Verbosity@@ -197,27 +174,30 @@ buildComponent verbosity numJobs pkg_descr lbi suffixes comp@(CLib lib) clbi distPref = do preprocessComponent pkg_descr comp lbi False verbosity suffixes+ extras <- preprocessExtras comp lbi info verbosity "Building library..."- buildLib verbosity numJobs pkg_descr lbi lib clbi+ let libbi = libBuildInfo lib+ lib' = lib { libBuildInfo = addExtraCSources libbi extras }+ buildLib verbosity numJobs pkg_descr lbi lib' clbi -- Register the library in-place, so exes can depend -- on internally defined libraries. pwd <- getCurrentDirectory let -- The in place registration uses the "-inplace" suffix, not an ABI hash- ipkgid = inplacePackageId (packageId installedPkgInfo) installedPkgInfo = inplaceInstalledPackageInfo pwd distPref pkg_descr- ipkgid lib lbi clbi-- registerPackage verbosity- installedPkgInfo pkg_descr lbi True -- True meaning in place- (withPackageDB lbi)+ (AbiHash "") lib' lbi clbi + registerPackage verbosity (compiler lbi) (withPrograms lbi) False+ (withPackageDB lbi) installedPkgInfo buildComponent verbosity numJobs pkg_descr lbi suffixes comp@(CExe exe) clbi _ = do preprocessComponent pkg_descr comp lbi False verbosity suffixes+ extras <- preprocessExtras comp lbi info verbosity $ "Building executable " ++ exeName exe ++ "..."- buildExe verbosity numJobs pkg_descr lbi exe clbi+ let ebi = buildInfo exe+ exe' = exe { buildInfo = addExtraCSources ebi extras }+ buildExe verbosity numJobs pkg_descr lbi exe' clbi buildComponent verbosity numJobs pkg_descr lbi suffixes@@ -225,8 +205,11 @@ clbi _distPref = do let exe = testSuiteExeV10AsExe test preprocessComponent pkg_descr comp lbi False verbosity suffixes+ extras <- preprocessExtras comp lbi info verbosity $ "Building test suite " ++ testName test ++ "..."- buildExe verbosity numJobs pkg_descr lbi exe clbi+ let ebi = buildInfo exe+ exe' = exe { buildInfo = addExtraCSources ebi extras }+ buildExe verbosity numJobs pkg_descr lbi exe' clbi buildComponent verbosity numJobs pkg_descr lbi0 suffixes@@ -242,10 +225,17 @@ let (pkg, lib, libClbi, lbi, ipi, exe, exeClbi) = testSuiteLibV09AsLibAndExe pkg_descr test clbi lbi0 distPref pwd preprocessComponent pkg_descr comp lbi False verbosity suffixes+ extras <- preprocessExtras comp lbi info verbosity $ "Building test suite " ++ testName test ++ "..." buildLib verbosity numJobs pkg lbi lib libClbi- registerPackage verbosity ipi pkg lbi True $ withPackageDB lbi- buildExe verbosity numJobs pkg_descr lbi exe exeClbi+ -- NB: need to enable multiple instances here, because on 7.10++ -- the package name is the same as the library, and we still+ -- want the registration to go through.+ registerPackage verbosity (compiler lbi) (withPrograms lbi) True+ (withPackageDB lbi) ipi+ let ebi = buildInfo exe+ exe' = exe { buildInfo = addExtraCSources ebi extras }+ buildExe verbosity numJobs pkg_descr lbi exe' exeClbi buildComponent _ _ _ _ _@@ -259,8 +249,11 @@ clbi _ = do let (exe, exeClbi) = benchmarkExeV10asExe bm clbi preprocessComponent pkg_descr comp lbi False verbosity suffixes+ extras <- preprocessExtras comp lbi info verbosity $ "Building benchmark " ++ benchmarkName bm ++ "..."- buildExe verbosity numJobs pkg_descr lbi exe exeClbi+ let ebi = buildInfo exe+ exe' = exe { buildInfo = addExtraCSources ebi extras }+ buildExe verbosity numJobs pkg_descr lbi exe' exeClbi buildComponent _ _ _ _ _@@ -269,6 +262,15 @@ die $ "No support for building benchmark type " ++ display tt +-- | Add extra C sources generated by preprocessing to build+-- information.+addExtraCSources :: BuildInfo -> [FilePath] -> BuildInfo+addExtraCSources bi extras = bi { cSources = new }+ where new = Set.toList $ old `Set.union` exs+ old = Set.fromList $ cSources bi+ exs = Set.fromList extras++ replComponent :: Verbosity -> PackageDescription -> LocalBuildInfo@@ -280,12 +282,18 @@ replComponent verbosity pkg_descr lbi suffixes comp@(CLib lib) clbi _ = do preprocessComponent pkg_descr comp lbi False verbosity suffixes- replLib verbosity pkg_descr lbi lib clbi+ extras <- preprocessExtras comp lbi+ let libbi = libBuildInfo lib+ lib' = lib { libBuildInfo = libbi { cSources = cSources libbi ++ extras } }+ replLib verbosity pkg_descr lbi lib' clbi replComponent verbosity pkg_descr lbi suffixes comp@(CExe exe) clbi _ = do preprocessComponent pkg_descr comp lbi False verbosity suffixes- replExe verbosity pkg_descr lbi exe clbi+ extras <- preprocessExtras comp lbi+ let ebi = buildInfo exe+ exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }+ replExe verbosity pkg_descr lbi exe' clbi replComponent verbosity pkg_descr lbi suffixes@@ -293,7 +301,10 @@ clbi _distPref = do let exe = testSuiteExeV10AsExe test preprocessComponent pkg_descr comp lbi False verbosity suffixes- replExe verbosity pkg_descr lbi exe clbi+ extras <- preprocessExtras comp lbi+ let ebi = buildInfo exe+ exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }+ replExe verbosity pkg_descr lbi exe' clbi replComponent verbosity pkg_descr lbi0 suffixes@@ -304,7 +315,10 @@ let (pkg, lib, libClbi, lbi, _, _, _) = testSuiteLibV09AsLibAndExe pkg_descr test clbi lbi0 distPref pwd preprocessComponent pkg_descr comp lbi False verbosity suffixes- replLib verbosity pkg lbi lib libClbi+ extras <- preprocessExtras comp lbi+ let libbi = libBuildInfo lib+ lib' = lib { libBuildInfo = libbi { cSources = cSources libbi ++ extras } }+ replLib verbosity pkg lbi lib' libClbi replComponent _ _ _ _@@ -318,7 +332,10 @@ clbi _ = do let (exe, exeClbi) = benchmarkExeV10asExe bm clbi preprocessComponent pkg_descr comp lbi False verbosity suffixes- replExe verbosity pkg_descr lbi exe exeClbi+ extras <- preprocessExtras comp lbi+ let ebi = buildInfo exe+ exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }+ replExe verbosity pkg_descr lbi exe' exeClbi replComponent _ _ _ _@@ -350,12 +367,12 @@ -> (PackageDescription, Library, ComponentLocalBuildInfo, LocalBuildInfo,- IPI.InstalledPackageInfo_ ModuleName,+ IPI.InstalledPackageInfo, Executable, ComponentLocalBuildInfo) testSuiteLibV09AsLibAndExe pkg_descr test@TestSuite { testInterface = TestSuiteLibV09 _ m } clbi lbi distPref pwd =- (pkg, lib, libClbi, lbi', ipi, exe, exeClbi)+ (pkg, lib, libClbi, lbi, ipi, exe, exeClbi) where bi = testBuildInfo test lib = Library {@@ -366,31 +383,31 @@ libExposed = True, libBuildInfo = bi }+ -- NB: temporary hack; I have a refactor which solves this+ cid = computeComponentId (package pkg_descr)+ (CTestName (testName test))+ (map ((\(SimpleUnitId cid0) -> cid0) . fst)+ (componentPackageDeps clbi))+ (flagAssignment lbi)+ uid = SimpleUnitId cid+ (pkg_name, compat_key) = computeCompatPackageKey+ (compiler lbi) (package pkg_descr)+ (CTestName (testName test)) uid libClbi = LibComponentLocalBuildInfo { componentPackageDeps = componentPackageDeps clbi , componentPackageRenaming = componentPackageRenaming clbi- , componentLibraries = [LibraryName (testName test)]- , componentExposedModules = [IPI.ExposedModule m Nothing Nothing]+ , componentUnitId = uid+ , componentCompatPackageKey = compat_key+ , componentExposedModules = [IPI.ExposedModule m Nothing] } pkg = pkg_descr {- package = (package pkg_descr) {- pkgName = PackageName (testName test)- }+ package = (package pkg_descr) { pkgName = pkg_name } , buildDepends = targetBuildDepends $ testBuildInfo test , executables = [] , testSuites = [] , library = Just lib }- -- Hack to make the library compile with the right package key.- -- Probably the "right" way to do this is move this information to- -- the ComponentLocalBuildInfo, but it seems odd that a single package- -- can define multiple actual packages.- lbi' = lbi {- pkgKey = mkPackageKey (packageKeySupported (compiler lbi))- (package pkg) [] []- }- ipkgid = inplacePackageId (packageId pkg)- ipi = inplaceInstalledPackageInfo pwd distPref pkg ipkgid lib lbi' libClbi+ ipi = inplaceInstalledPackageInfo pwd distPref pkg (AbiHash "") lib lbi libClbi testDir = buildDir lbi </> stubName test </> stubName test ++ "-tmp" testLibDep = thisPackageVersion $ package pkg@@ -401,22 +418,18 @@ hsSourceDirs = [ testDir ], targetBuildDepends = testLibDep : (targetBuildDepends $ testBuildInfo test),- targetBuildRenaming =- Map.insert (packageName pkg) defaultRenaming- (targetBuildRenaming $ testBuildInfo test)+ targetBuildRenaming = Map.empty } } -- | The stub executable needs a new 'ComponentLocalBuildInfo' -- that exposes the relevant test suite library. exeClbi = ExeComponentLocalBuildInfo { componentPackageDeps =- (IPI.installedPackageId ipi, packageId ipi)+ (IPI.installedUnitId ipi, packageId ipi) : (filter (\(_, x) -> let PackageName name = pkgName x in name == "Cabal" || name == "base") (componentPackageDeps clbi)),- componentPackageRenaming =- Map.insert (packageName ipi) defaultRenaming- (componentPackageRenaming clbi)+ componentPackageRenaming = Map.empty } testSuiteLibV09AsLibAndExe _ TestSuite{} _ _ _ _ = error "testSuiteLibV09AsLibAndExe: wrong kind" @@ -444,24 +457,14 @@ createInternalPackageDB :: Verbosity -> LocalBuildInfo -> FilePath -> IO PackageDB createInternalPackageDB verbosity lbi distPref = do- case compilerFlavor (compiler lbi) of- GHC -> createWith $ GHC.hcPkgInfo (withPrograms lbi)- GHCJS -> createWith $ GHCJS.hcPkgInfo (withPrograms lbi)- LHC -> createWith $ LHC.hcPkgInfo (withPrograms lbi)- _ -> return packageDB- where- dbPath = distPref </> "package.conf.inplace"- packageDB = SpecificPackageDB dbPath- createWith hpi = do- dir_exists <- doesDirectoryExist dbPath- if dir_exists- then removeDirectoryRecursive dbPath- else do file_exists <- doesFileExist dbPath- when file_exists $ removeFile dbPath- if HcPkg.useSingleFileDb hpi- then writeFile dbPath "[]"- else HcPkg.init hpi verbosity dbPath- return packageDB+ existsAlready <- doesPackageDBExist dbPath+ when existsAlready $ deletePackageDB dbPath+ createPackageDB verbosity (compiler lbi) (withPrograms lbi) False dbPath + return (SpecificPackageDB dbPath)+ where+ dbPath = case compilerFlavor (compiler lbi) of+ UHC -> UHC.inplacePackageDbPath lbi+ _ -> distPref </> "package.conf.inplace" addInternalBuildTools :: PackageDescription -> LocalBuildInfo -> BuildInfo -> ProgramDb -> ProgramDb@@ -532,12 +535,10 @@ -> IO () initialBuildSteps _distPref pkg_descr lbi verbosity = do -- check that there's something to build- let buildInfos =- map libBuildInfo (maybeToList (library pkg_descr)) ++- map buildInfo (executables pkg_descr)- unless (any buildable buildInfos) $ do+ unless (not . null $ allBuildInfo pkg_descr) $ do let name = display (packageId pkg_descr)- die ("Package " ++ name ++ " can't be built on this system.")+ die $ "No libraries, executables, tests, or benchmarks "+ ++ "are enabled for package " ++ name ++ "." createDirectoryIfMissingVerbose verbosity True (buildDir lbi)
Distribution/Simple/Build/Macros.hs view
@@ -29,11 +29,10 @@ import Distribution.Version ( Version(versionBranch) ) import Distribution.PackageDescription- ( PackageDescription )-import Distribution.Simple.Compiler- ( packageKeySupported )+ ( PackageDescription ( package ) ) import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(compiler, pkgKey, withPrograms), externalPackageDeps )+ ( LocalBuildInfo(withPrograms), externalPackageDeps+ , localComponentId, localCompatPackageKey ) import Distribution.Simple.Program.Db ( configuredPrograms ) import Distribution.Simple.Program.Types@@ -48,11 +47,12 @@ -- | The contents of the @cabal_macros.h@ for the given configured package. -- generate :: PackageDescription -> LocalBuildInfo -> String-generate _pkg_descr lbi =+generate pkg_descr lbi = "/* DO NOT EDIT: This file is automatically generated by Cabal */\n\n" ++- generatePackageVersionMacros (map snd (externalPackageDeps lbi)) +++ generatePackageVersionMacros+ (package pkg_descr : map snd (externalPackageDeps lbi)) ++ generateToolVersionMacros (configuredPrograms . withPrograms $ lbi) ++- generatePackageKeyMacro lbi+ generateComponentIdMacro lbi -- | Helper function that generates just the @VERSION_pkg@ and @MIN_VERSION_pkg@ -- macros for a list of package ids (usually used with the specific deps of@@ -96,13 +96,14 @@ where (major1:major2:minor:_) = map show (versionBranch version ++ repeat 0) --- | Generate the @CURRENT_PACKAGE_KEY@ definition for the package key--- of the current package, if supported by the compiler-generatePackageKeyMacro :: LocalBuildInfo -> String-generatePackageKeyMacro lbi- | packageKeySupported (compiler lbi) =- "#define CURRENT_PACKAGE_KEY \"" ++ display (pkgKey lbi) ++ "\"\n\n"- | otherwise = ""+-- | Generate the @CURRENT_COMPONENT_ID@ definition for the component ID+-- of the current package.+generateComponentIdMacro :: LocalBuildInfo -> String+generateComponentIdMacro lbi =+ concat+ [ "#define CURRENT_COMPONENT_ID \"" ++ display (localComponentId lbi) ++ "\"\n\n"+ , "#define CURRENT_PACKAGE_KEY \"" ++ localCompatPackageKey lbi ++ "\"\n\n"+ ] fixchar :: Char -> Char fixchar '-' = '_'
Distribution/Simple/Build/PathsModule.hs view
@@ -19,25 +19,14 @@ ) where import Distribution.System- ( OS(Windows), buildOS, Arch(..), buildArch ) import Distribution.Simple.Compiler- ( CompilerFlavor(..), compilerFlavor, compilerVersion ) import Distribution.Package- ( packageId, packageName, packageVersion ) import Distribution.PackageDescription- ( PackageDescription(..), hasLibs ) import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), InstallDirs(..)- , absoluteInstallDirs, prefixRelativeInstallDirs )-import Distribution.Simple.Setup ( CopyDest(NoCopyDest) ) import Distribution.Simple.BuildPaths- ( autogenModuleName ) import Distribution.Simple.Utils- ( shortRelativePath ) import Distribution.Text- ( display ) import Distribution.Version- ( Version(..), orLaterVersion, withinRange ) import System.FilePath ( pathSeparator )@@ -50,7 +39,12 @@ generate :: PackageDescription -> LocalBuildInfo -> String generate pkg_descr lbi =- let pragmas+ let pragmas = cpp_pragma ++ ffi_pragmas ++ warning_pragmas++ cpp_pragma | supports_cpp = "{-# LANGUAGE CPP #-}\n"+ | otherwise = ""++ ffi_pragmas | absolute = "" | supports_language_pragma = "{-# LANGUAGE ForeignFunctionInterface #-}\n"@@ -58,6 +52,10 @@ "{-# OPTIONS_GHC -fffi #-}\n"++ "{-# OPTIONS_JHC -fffi #-}\n" + warning_pragmas =+ "{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}\n"+++ "{-# OPTIONS_GHC -fno-warn-implicit-prelude #-}\n"+ foreign_imports | absolute = "" | otherwise =@@ -84,7 +82,21 @@ reloc_imports ++ "import Prelude\n"++ "\n"++- "catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a\n"+++ (if supports_cpp+ then+ ("#if defined(VERSION_base)\n"+++ "\n"+++ "#if MIN_VERSION_base(4,0,0)\n"+++ "catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a\n"+++ "#else\n"+++ "catchIO :: IO a -> (Exception.Exception -> IO a) -> IO a\n"+++ "#endif\n"+++ "\n"+++ "#else\n"+++ "catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a\n"+++ "#endif\n")+ else+ "catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a\n")++ "catchIO = Exception.catch\n" ++ "\n"++ "version :: Version"++@@ -212,6 +224,8 @@ get_prefix_stuff = get_prefix_win32 buildArch path_sep = show [pathSeparator]++ supports_cpp = compilerFlavor (compiler lbi) == GHC supports_language_pragma = (compilerFlavor (compiler lbi) == GHC &&
Distribution/Simple/BuildPaths.hs view
@@ -31,22 +31,17 @@ ) where -import System.FilePath ((</>), (<.>))- import Distribution.Package- ( packageName )-import Distribution.ModuleName (ModuleName)-import qualified Distribution.ModuleName as ModuleName+import Distribution.ModuleName as ModuleName import Distribution.Compiler- ( CompilerId(..) )-import Distribution.PackageDescription (PackageDescription)+import Distribution.PackageDescription import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(buildDir), LibraryName(..) )-import Distribution.Simple.Setup (defaultDistPref)+import Distribution.Simple.Setup import Distribution.Text- ( display )-import Distribution.System (OS(..), buildOS)+import Distribution.System +import System.FilePath ((</>), (<.>))+ -- --------------------------------------------------------------------------- -- Build directories and files @@ -81,33 +76,31 @@ -- --------------------------------------------------------------------------- -- Library file names -mkLibName :: LibraryName -> String-mkLibName (LibraryName lib) = "lib" ++ lib <.> "a"+mkLibName :: UnitId -> String+mkLibName lib = "lib" ++ getHSLibraryName lib <.> "a" -mkProfLibName :: LibraryName -> String-mkProfLibName (LibraryName lib) = "lib" ++ lib ++ "_p" <.> "a"+mkProfLibName :: UnitId -> String+mkProfLibName lib = "lib" ++ getHSLibraryName lib ++ "_p" <.> "a" -- Implement proper name mangling for dynamical shared objects -- libHS<packagename>-<compilerFlavour><compilerVersion> -- e.g. libHSbase-2.1-ghc6.6.1.so-mkSharedLibName :: CompilerId -> LibraryName -> String-mkSharedLibName (CompilerId compilerFlavor compilerVersion) (LibraryName lib)- = "lib" ++ lib ++ "-" ++ comp <.> dllExtension+mkSharedLibName :: CompilerId -> UnitId -> String+mkSharedLibName (CompilerId compilerFlavor compilerVersion) lib+ = "lib" ++ getHSLibraryName lib ++ "-" ++ comp <.> dllExtension where comp = display compilerFlavor ++ display compilerVersion -- ------------------------------------------------------------ -- * Platform file extensions -- ------------------------------------------------------------ --- ToDo: This should be determined via autoconf (AC_EXEEXT)--- | Extension for executable files+-- | Default extension for executable files on the current platform. -- (typically @\"\"@ on Unix and @\"exe\"@ on Windows or OS\/2) exeExtension :: String exeExtension = case buildOS of Windows -> "exe" _ -> "" --- TODO: This should be determined via autoconf (AC_OBJEXT) -- | Extension for object files. For GHC the extension is @\"o\"@. objExtension :: String objExtension = "o"
Distribution/Simple/BuildTarget.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Client.BuildTargets@@ -14,10 +14,14 @@ -- * Build targets BuildTarget(..), readBuildTargets,+ showBuildTarget,+ QualLevel(..),+ buildTargetComponentName, -- * Parsing user build targets UserBuildTarget, readUserBuildTargets,+ showUserBuildTarget, UserBuildTargetProblem(..), reportUserBuildTargetProblems, @@ -28,41 +32,27 @@ ) where import Distribution.Package- ( Package(..), PackageId, packageName )- import Distribution.PackageDescription- ( PackageDescription- , Executable(..)- , TestSuite(..), TestSuiteInterface(..), testModules- , Benchmark(..), BenchmarkInterface(..), benchmarkModules- , BuildInfo(..), libModules, exeModules ) import Distribution.ModuleName- ( ModuleName, toFilePath ) import Distribution.Simple.LocalBuildInfo- ( Component(..), ComponentName(..)- , pkgComponents, componentName, componentBuildInfo )- import Distribution.Text- ( display ) import Distribution.Simple.Utils- ( die, lowercase, equating ) +import Distribution.Compat.Binary (Binary)+import qualified Distribution.Compat.ReadP as Parse+import Distribution.Compat.ReadP+ ( (+++), (<++) )+ import Data.List- ( nub, stripPrefix, sortBy, groupBy, partition, intercalate )-import Data.Ord+ ( nub, stripPrefix, sortBy, groupBy, partition ) import Data.Maybe ( listToMaybe, catMaybes ) import Data.Either ( partitionEithers )+import GHC.Generics (Generic) import qualified Data.Map as Map import Control.Monad-#if __GLASGOW_HASKELL__ < 710-import Control.Applicative (Applicative(..))-#endif-import Control.Applicative (Alternative(..))-import qualified Distribution.Compat.ReadP as Parse-import Distribution.Compat.ReadP- ( (+++), (<++) )+import Control.Applicative as AP (Alternative(..), Applicative(..)) import Data.Char ( isSpace, isAlphaNum ) import System.FilePath as FilePath@@ -127,13 +117,19 @@ -- | A specific file within a specific component. -- | BuildTargetFile ComponentName FilePath- deriving (Show,Eq)+ deriving (Eq, Show, Generic) +instance Binary BuildTarget --- --------------------------------------------------------------- * Do everything--- ------------------------------------------------------------+buildTargetComponentName :: BuildTarget -> ComponentName+buildTargetComponentName (BuildTargetComponent cn) = cn+buildTargetComponentName (BuildTargetModule cn _) = cn+buildTargetComponentName (BuildTargetFile cn _) = cn +-- | Read a list of user-supplied build target strings and resolve them to+-- 'BuildTarget's according to a 'PackageDescription'. If there are problems+-- with any of the targets e.g. they don't exist or are misformatted, throw an+-- 'IOException'. readBuildTargets :: PackageDescription -> [String] -> IO [BuildTarget] readBuildTargets pkg targetStrs = do let (uproblems, utargets) = readUserBuildTargets targetStrs@@ -226,13 +222,17 @@ ++ " - build foo:Data/Foo.hsc -- file qualified by component" showUserBuildTarget :: UserBuildTarget -> String-showUserBuildTarget = intercalate ":" . components+showUserBuildTarget = intercalate ":" . getComponents where- components (UserBuildTargetSingle s1) = [s1]- components (UserBuildTargetDouble s1 s2) = [s1,s2]- components (UserBuildTargetTriple s1 s2 s3) = [s1,s2,s3]+ getComponents (UserBuildTargetSingle s1) = [s1]+ getComponents (UserBuildTargetDouble s1 s2) = [s1,s2]+ getComponents (UserBuildTargetTriple s1 s2 s3) = [s1,s2,s3] +showBuildTarget :: QualLevel -> PackageId -> BuildTarget -> String+showBuildTarget ql pkgid bt =+ showUserBuildTarget (renderBuildTarget ql bt pkgid) + -- ------------------------------------------------------------ -- * Resolving user targets to build targets -- ------------------------------------------------------------@@ -265,7 +265,7 @@ resolveBuildTarget pkg userTarget fexists = case findMatch (matchBuildTarget pkg userTarget fexists) of Unambiguous target -> Right target- Ambiguous targets -> Left (BuildTargetAmbigious userTarget targets')+ Ambiguous targets -> Left (BuildTargetAmbiguous userTarget targets') where targets' = disambiguateBuildTargets (packageId pkg) userTarget targets@@ -287,7 +287,7 @@ -- ^ [expected thing] (actually got) | BuildTargetNoSuch UserBuildTarget [(String, String)] -- ^ [(no such thing, actually got)]- | BuildTargetAmbigious UserBuildTarget [(UserBuildTarget, BuildTarget)]+ | BuildTargetAmbiguous UserBuildTarget [(UserBuildTarget, BuildTarget)] deriving Show @@ -366,7 +366,7 @@ mungeThing "file" = "file target" mungeThing thing = thing - case [ (t, ts) | BuildTargetAmbigious t ts <- problems ] of+ case [ (t, ts) | BuildTargetAmbiguous t ts <- problems ] of [] -> return () targets -> die $ unlines@@ -734,10 +734,10 @@ -- -- | A matcher embodies a way to match some input as being some recognised--- value. In particular it deals with multiple and ambigious matches.+-- value. In particular it deals with multiple and ambiguous matches. -- -- There are various matcher primitives ('matchExactly', 'matchInexactly'),--- ways to combine matchers ('ambigiousWith', 'shadows') and finally we can+-- ways to combine matchers ('ambiguousWith', 'shadows') and finally we can -- run a matcher against an input using 'findMatch'. -- @@ -766,7 +766,7 @@ -- | Combine two matchers. Exact matches are used over inexact matches -- but if we have multiple exact, or inexact then the we collect all the--- ambigious matches.+-- ambiguous matches. -- matchPlus :: Match a -> Match a -> Match a matchPlus (ExactMatch d1 xs) (ExactMatch d2 xs') =@@ -784,7 +784,7 @@ | d1 < d2 = b | otherwise = NoMatch d1 (ms ++ ms') --- | Combine two matchers. This is similar to 'ambigiousWith' with the+-- | Combine two matchers. This is similar to 'ambiguousWith' with the -- difference that an exact match from the left matcher shadows any exact -- match on the right. Inexact matches are still collected however. --@@ -798,11 +798,12 @@ fmap f (InexactMatch d xs) = InexactMatch d (fmap f xs) instance Applicative Match where- pure = return+ pure a = ExactMatch 0 [a] (<*>) = ap instance Monad Match where- return a = ExactMatch 0 [a]+ return = AP.pure+ NoMatch d ms >>= _ = NoMatch d ms ExactMatch d xs >>= f = addDepth d $ foldr matchPlus matchZero (map f xs)@@ -872,18 +873,18 @@ -- possible matches. There may be 'None', a single 'Unambiguous' match or -- you may have an 'Ambiguous' match with several possibilities. ---findMatch :: Eq b => Match b -> MaybeAmbigious b+findMatch :: Eq b => Match b -> MaybeAmbiguous b findMatch match = case match of NoMatch _ msgs -> None (nub msgs)- ExactMatch _ xs -> checkAmbigious xs- InexactMatch _ xs -> checkAmbigious xs+ ExactMatch _ xs -> checkAmbiguous xs+ InexactMatch _ xs -> checkAmbiguous xs where- checkAmbigious xs = case nub xs of+ checkAmbiguous xs = case nub xs of [x] -> Unambiguous x xs' -> Ambiguous xs' -data MaybeAmbigious a = None [MatchError] | Unambiguous a | Ambiguous [a]+data MaybeAmbiguous a = None [MatchError] | Unambiguous a | Ambiguous [a] deriving Show
Distribution/Simple/CCompiler.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Simple.CCompiler@@ -47,10 +46,8 @@ filenameCDialect ) where -#if __GLASGOW_HASKELL__ < 710-import Data.Monoid- ( Monoid(..) )-#endif+import Distribution.Compat.Semigroup as Semi+ import System.FilePath ( takeExtension ) @@ -66,15 +63,16 @@ instance Monoid CDialect where mempty = C-- mappend C anything = anything- mappend ObjectiveC CPlusPlus = ObjectiveCPlusPlus- mappend CPlusPlus ObjectiveC = ObjectiveCPlusPlus- mappend _ ObjectiveCPlusPlus = ObjectiveCPlusPlus- mappend ObjectiveC _ = ObjectiveC- mappend CPlusPlus _ = CPlusPlus- mappend ObjectiveCPlusPlus _ = ObjectiveCPlusPlus+ mappend = (Semi.<>) +instance Semigroup CDialect where+ C <> anything = anything+ ObjectiveC <> CPlusPlus = ObjectiveCPlusPlus+ CPlusPlus <> ObjectiveC = ObjectiveCPlusPlus+ _ <> ObjectiveCPlusPlus = ObjectiveCPlusPlus+ ObjectiveC <> _ = ObjectiveC+ CPlusPlus <> _ = CPlusPlus+ ObjectiveCPlusPlus <> _ = ObjectiveCPlusPlus -- | A list of all file extensions which are recognized as possibly containing -- some dialect of C code. Note that this list is only for source files,
Distribution/Simple/Command.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE ExistentialQuantification #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Simple.Command@@ -6,7 +6,7 @@ -- License : BSD3 -- -- Maintainer : cabal-devel@haskell.org--- Portability : portable+-- Portability : non-portable (ExistentialQuantification) -- -- This is to do with command line handling. The Cabal command line is -- organised into a number of named sub-commands (much like darcs). The@@ -38,6 +38,11 @@ commandAddAction, noExtraFlags, + -- ** Building lists of commands+ CommandType(..),+ CommandSpec(..),+ commandFromSpec,+ -- ** Running commands commandsRun, @@ -60,19 +65,17 @@ ) where -import Control.Monad-import Data.Char (isAlpha, toLower)-import Data.List (sortBy)-import Data.Maybe-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid-#endif import qualified Distribution.GetOpt as GetOpt import Distribution.Text- ( Text(disp, parse) ) import Distribution.ParseUtils import Distribution.ReadE-import Distribution.Simple.Utils (die, intercalate)+import Distribution.Simple.Utils++import Control.Monad+import Data.Char (isAlpha, toLower)+import Data.List (sortBy)+import Data.Maybe+import Data.Monoid as Mon import Text.PrettyPrint ( punctuate, cat, comma, text ) import Text.PrettyPrint as PP ( empty ) @@ -171,14 +174,14 @@ reqArg ad (succeedReadE mkflag) showflag -- | (String -> a) variant of "optArg"-optArg' :: Monoid b => ArgPlaceHolder -> (Maybe String -> b)+optArg' :: Mon.Monoid b => ArgPlaceHolder -> (Maybe String -> b) -> (b -> [Maybe String]) -> MkOptDescr (a -> b) (b -> a -> a) a optArg' ad mkflag showflag = optArg ad (succeedReadE (mkflag . Just)) def showflag where def = mkflag Nothing -noArg :: (Eq b, Monoid b) => b -> MkOptDescr (a -> b) (b -> a -> a) a+noArg :: (Eq b) => b -> MkOptDescr (a -> b) (b -> a -> a) a noArg flag sf lf d = choiceOpt [(flag, (sf,lf), d)] sf lf d boolOpt :: (b -> Maybe Bool) -> (Bool -> b) -> SFlags -> SFlags@@ -592,9 +595,26 @@ | Command name description _ NormalCommand <- cmds ] helpCommandUI :: CommandUI ()-helpCommandUI = mkCommandUI- "help"- "Help about commands."- ["[FLAGS]", "COMMAND [FLAGS]"]- ()- (const [])+helpCommandUI =+ (mkCommandUI+ "help"+ "Help about commands."+ ["[FLAGS]", "COMMAND [FLAGS]"]+ ()+ (const []))+ {+ commandNotes = Just $ \pname ->+ "Examples:\n"+ ++ " " ++ pname ++ " help help\n"+ ++ " Oh, appararently you already know this.\n"+ }++-- | wraps a @CommandUI@ together with a function that turns it into a @Command@.+-- By hiding the type of flags for the UI allows construction of a list of all UIs at the+-- top level of the program. That list can then be used for generation of manual page+-- as well as for executing the selected command.+data CommandSpec action+ = forall flags. CommandSpec (CommandUI flags) (CommandUI flags -> Command action) CommandType++commandFromSpec :: CommandSpec a -> Command a+commandFromSpec (CommandSpec ui action _) = action ui
Distribution/Simple/Compiler.hs view
@@ -53,16 +53,25 @@ parmakeSupported, reexportedModulesSupported, renamingPackageFlagsSupported,- packageKeySupported+ unifiedIPIDRequired,+ packageKeySupported,+ unitIdSupported,++ -- * Support for profiling detail levels+ ProfDetailLevel(..),+ knownProfDetailLevels,+ flagToProfDetailLevel,+ showProfDetailLevel, ) where import Distribution.Compiler-import Distribution.Version (Version(..))-import Distribution.Text (display)-import Language.Haskell.Extension (Language(Haskell98), Extension)+import Distribution.Version+import Distribution.Text+import Language.Haskell.Extension+import Distribution.Simple.Utils+import Distribution.Compat.Binary import Control.Monad (liftM)-import Distribution.Compat.Binary (Binary) import Data.List (nub) import qualified Data.Map as M (Map, lookup) import Data.Maybe (catMaybes, isNothing, listToMaybe)@@ -83,7 +92,7 @@ compilerProperties :: M.Map String String -- ^ A key-value map for properties not covered by the above fields. }- deriving (Generic, Show, Read)+ deriving (Eq, Generic, Show, Read) instance Binary Compiler @@ -270,10 +279,18 @@ renamingPackageFlagsSupported :: Compiler -> Bool renamingPackageFlagsSupported = ghcSupported "Support thinning and renaming package flags" +-- | Does this compiler have unified IPIDs (so no package keys)+unifiedIPIDRequired :: Compiler -> Bool+unifiedIPIDRequired = ghcSupported "Requires unified installed package IDs"+ -- | Does this compiler support package keys? packageKeySupported :: Compiler -> Bool packageKeySupported = ghcSupported "Uses package keys" +-- | Does this compiler support unit IDs?+unitIdSupported :: Compiler -> Bool+unitIdSupported = ghcSupported "Uses unit IDs"+ -- | Utility function for GHC only features ghcSupported :: String -> Compiler -> Bool ghcSupported key comp =@@ -285,3 +302,53 @@ case M.lookup key (compilerProperties comp) of Just "YES" -> True _ -> False++-- ------------------------------------------------------------+-- * Profiling detail level+-- ------------------------------------------------------------++-- | Some compilers (notably GHC) support profiling and can instrument+-- programs so the system can account costs to different functions. There are+-- different levels of detail that can be used for this accounting.+-- For compilers that do not support this notion or the particular detail+-- levels, this is either ignored or just capped to some similar level+-- they do support.+--+data ProfDetailLevel = ProfDetailNone+ | ProfDetailDefault+ | ProfDetailExportedFunctions+ | ProfDetailToplevelFunctions+ | ProfDetailAllFunctions+ | ProfDetailOther String+ deriving (Eq, Generic, Read, Show)++instance Binary ProfDetailLevel++flagToProfDetailLevel :: String -> ProfDetailLevel+flagToProfDetailLevel "" = ProfDetailDefault+flagToProfDetailLevel s =+ case lookup (lowercase s)+ [ (name, value)+ | (primary, aliases, value) <- knownProfDetailLevels+ , name <- primary : aliases ]+ of Just value -> value+ Nothing -> ProfDetailOther s++knownProfDetailLevels :: [(String, [String], ProfDetailLevel)]+knownProfDetailLevels =+ [ ("default", [], ProfDetailDefault)+ , ("none", [], ProfDetailNone)+ , ("exported-functions", ["exported"], ProfDetailExportedFunctions)+ , ("toplevel-functions", ["toplevel", "top"], ProfDetailToplevelFunctions)+ , ("all-functions", ["all"], ProfDetailAllFunctions)+ ]++showProfDetailLevel :: ProfDetailLevel -> String+showProfDetailLevel dl = case dl of+ ProfDetailNone -> "none"+ ProfDetailDefault -> "default"+ ProfDetailExportedFunctions -> "exported-functions"+ ProfDetailToplevelFunctions -> "toplevel-functions"+ ProfDetailAllFunctions -> "all-functions"+ ProfDetailOther other -> other+
Distribution/Simple/Configure.hs view
@@ -1,1432 +1,1778 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Configure--- Copyright : Isaac Jones 2003-2005--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This deals with the /configure/ phase. It provides the 'configure' action--- which is given the package description and configure flags. It then tries--- to: configure the compiler; resolves any conditionals in the package--- description; resolve the package dependencies; check if all the extensions--- used by this package are supported by the compiler; check that all the build--- tools are available (including version checks if appropriate); checks for--- any required @pkg-config@ packages (updating the 'BuildInfo' with the--- results)------ Then based on all this it saves the info in the 'LocalBuildInfo' and writes--- it out to the @dist\/setup-config@ file. It also displays various details to--- the user, the amount of information displayed depending on the verbosity--- level.--module Distribution.Simple.Configure (configure,- writePersistBuildConfig,- getConfigStateFile,- getPersistBuildConfig,- checkPersistBuildConfigOutdated,- tryGetPersistBuildConfig,- maybeGetPersistBuildConfig,- localBuildInfoFile,- getInstalledPackages, getPackageDBContents,- configCompiler, configCompilerAux,- configCompilerEx, configCompilerAuxEx,- ccLdOptionsBuildInfo,- checkForeignDeps,- interpretPackageDbFlags,- ConfigStateFileError(..),- tryGetConfigStateFile,- platformDefines,- )- where--import Distribution.Compiler- ( CompilerId(..) )-import Distribution.Utils.NubList-import Distribution.Simple.Compiler- ( CompilerFlavor(..), Compiler(..), compilerFlavor, compilerVersion- , compilerInfo- , showCompilerId, unsupportedLanguages, unsupportedExtensions- , PackageDB(..), PackageDBStack, reexportedModulesSupported- , packageKeySupported, renamingPackageFlagsSupported )-import Distribution.Simple.PreProcess ( platformDefines )-import Distribution.Package- ( PackageName(PackageName), PackageIdentifier(..), PackageId- , packageName, packageVersion, Package(..)- , Dependency(Dependency), simplifyDependency- , InstalledPackageId(..), thisPackageVersion- , mkPackageKey, PackageKey(..), packageKeyLibraryName )-import qualified Distribution.InstalledPackageInfo as Installed-import Distribution.InstalledPackageInfo (InstalledPackageInfo, emptyInstalledPackageInfo)-import qualified Distribution.Simple.PackageIndex as PackageIndex-import Distribution.Simple.PackageIndex (InstalledPackageIndex)-import Distribution.PackageDescription as PD- ( PackageDescription(..), specVersion, GenericPackageDescription(..)- , Library(..), hasLibs, Executable(..), BuildInfo(..), allExtensions- , HookedBuildInfo, updatePackageDescription, allBuildInfo- , Flag(flagName), FlagName(..), TestSuite(..), Benchmark(..)- , ModuleReexport(..) , defaultRenaming )-import Distribution.ModuleName- ( ModuleName )-import Distribution.PackageDescription.Configuration- ( finalizePackageDescription, mapTreeData )-import Distribution.PackageDescription.Check- ( PackageCheck(..), checkPackage, checkPackageFiles )-import Distribution.Simple.Program- ( Program(..), ProgramLocation(..), ConfiguredProgram(..)- , ProgramConfiguration, defaultProgramConfiguration- , ProgramSearchPathEntry(..), getProgramSearchPath, setProgramSearchPath- , configureAllKnownPrograms, knownPrograms, lookupKnownProgram- , userSpecifyArgss, userSpecifyPaths- , lookupProgram, requireProgram, requireProgramVersion- , pkgConfigProgram, gccProgram, rawSystemProgramStdoutConf )-import Distribution.Simple.Setup- ( ConfigFlags(..), CopyDest(..), Flag(..), fromFlag, fromFlagOrDefault- , flagToMaybe )-import Distribution.Simple.InstallDirs- ( InstallDirs(..), defaultInstallDirs, combineInstallDirs )-import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), Component(..), ComponentLocalBuildInfo(..)- , LibraryName(..)- , absoluteInstallDirs, prefixRelativeInstallDirs, inplacePackageId- , ComponentName(..), showComponentName, pkgEnabledComponents- , componentBuildInfo, componentName, checkComponentsCyclic )-import Distribution.Simple.BuildPaths- ( autogenModulesDir )-import Distribution.Simple.Utils- ( die, warn, info, setupMessage- , createDirectoryIfMissingVerbose, moreRecentFile- , intercalate, cabalVersion- , writeFileAtomic- , withTempFile )-import Distribution.System- ( OS(..), buildOS, Platform (..), buildPlatform )-import Distribution.Version- ( Version(..), anyVersion, orLaterVersion, withinRange, isAnyVersion )-import Distribution.Verbosity- ( Verbosity, lessVerbose )--import qualified Distribution.Simple.GHC as GHC-import qualified Distribution.Simple.GHCJS as GHCJS-import qualified Distribution.Simple.JHC as JHC-import qualified Distribution.Simple.LHC as LHC-import qualified Distribution.Simple.UHC as UHC-import qualified Distribution.Simple.HaskellSuite as HaskellSuite---- Prefer the more generic Data.Traversable.mapM to Prelude.mapM-import Prelude hiding ( mapM )-import Control.Exception- ( ErrorCall(..), Exception, evaluate, throw, throwIO, try )-import Control.Monad- ( liftM, when, unless, foldM, filterM )-import Distribution.Compat.Binary ( decodeOrFailIO, encode )-import Data.ByteString.Lazy (ByteString)-import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy.Char8 as BLC8-import Data.List- ( (\\), nub, partition, isPrefixOf, inits, stripPrefix )-import Data.Maybe- ( isNothing, catMaybes, fromMaybe, isJust )-import Data.Either- ( partitionEithers )-import qualified Data.Set as Set-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid- ( Monoid(..) )-#endif-import qualified Data.Map as Map-import Data.Map (Map)-import Data.Traversable- ( mapM )-import Data.Typeable-import System.Directory- ( doesFileExist, createDirectoryIfMissing, getTemporaryDirectory )-import System.FilePath- ( (</>), isAbsolute )-import qualified System.Info- ( compilerName, compilerVersion )-import System.IO- ( hPutStrLn, hClose )-import Distribution.Text- ( Text(disp), display, simpleParse )-import Text.PrettyPrint- ( render, (<>), ($+$), char, text, comma- , quotes, punctuate, nest, sep, hsep )-import Distribution.Compat.Exception ( catchExit, catchIO )--data ConfigStateFileError- = ConfigStateFileNoHeader- | ConfigStateFileBadHeader- | ConfigStateFileNoParse- | ConfigStateFileMissing- | ConfigStateFileBadVersion PackageIdentifier PackageIdentifier (Either ConfigStateFileError LocalBuildInfo)- deriving (Typeable)--instance Show ConfigStateFileError where- show ConfigStateFileNoHeader =- "Saved package config file header is missing. "- ++ "Try re-running the 'configure' command."- show ConfigStateFileBadHeader =- "Saved package config file header is corrupt. "- ++ "Try re-running the 'configure' command."- show ConfigStateFileNoParse =- "Saved package config file body is corrupt. "- ++ "Try re-running the 'configure' command."- show ConfigStateFileMissing = "Run the 'configure' command first."- show (ConfigStateFileBadVersion oldCabal oldCompiler _) =- "You need to re-run the 'configure' command. "- ++ "The version of Cabal being used has changed (was "- ++ display oldCabal ++ ", now "- ++ display currentCabalId ++ ")."- ++ badCompiler- where- badCompiler- | oldCompiler == currentCompilerId = ""- | otherwise =- " Additionally the compiler is different (was "- ++ display oldCompiler ++ ", now "- ++ display currentCompilerId- ++ ") which is probably the cause of the problem."--instance Exception ConfigStateFileError--getConfigStateFile :: FilePath -> IO LocalBuildInfo-getConfigStateFile filename = do- exists <- doesFileExist filename- unless exists $ throwIO ConfigStateFileMissing- -- Read the config file into a strict ByteString to avoid problems with- -- lazy I/O, then convert to lazy because the binary package needs that.- contents <- BS.readFile filename- let (header, body) = BLC8.span (/='\n') (BLC8.fromChunks [contents])-- headerParseResult <- try $ evaluate $ parseHeader header- let (cabalId, compId) =- case headerParseResult of- Left (ErrorCall _) -> throw ConfigStateFileBadHeader- Right x -> x-- let getStoredValue = do- result <- decodeOrFailIO (BLC8.tail body)- case result of- Left _ -> throw ConfigStateFileNoParse- Right x -> return x- deferErrorIfBadVersion act- | cabalId /= currentCabalId = do- eResult <- try act- throw $ ConfigStateFileBadVersion cabalId compId eResult- | otherwise = act- deferErrorIfBadVersion getStoredValue--tryGetConfigStateFile :: FilePath- -> IO (Either ConfigStateFileError LocalBuildInfo)-tryGetConfigStateFile = try . getConfigStateFile---- |Try to read the 'localBuildInfoFile'.-tryGetPersistBuildConfig :: FilePath- -> IO (Either ConfigStateFileError LocalBuildInfo)-tryGetPersistBuildConfig = try . getPersistBuildConfig---- | Read the 'localBuildInfoFile'. Throw an exception if the file is--- missing, if the file cannot be read, or if the file was created by an older--- version of Cabal.-getPersistBuildConfig :: FilePath -> IO LocalBuildInfo-getPersistBuildConfig = getConfigStateFile . localBuildInfoFile---- |Try to read the 'localBuildInfoFile'.-maybeGetPersistBuildConfig :: FilePath -> IO (Maybe LocalBuildInfo)-maybeGetPersistBuildConfig =- liftM (either (const Nothing) Just) . tryGetPersistBuildConfig---- |After running configure, output the 'LocalBuildInfo' to the--- 'localBuildInfoFile'.-writePersistBuildConfig :: FilePath -> LocalBuildInfo -> IO ()-writePersistBuildConfig distPref lbi = do- createDirectoryIfMissing False distPref- writeFileAtomic (localBuildInfoFile distPref) $- BLC8.unlines [showHeader pkgId, encode lbi]- where- pkgId = packageId $ localPkgDescr lbi--currentCabalId :: PackageIdentifier-currentCabalId = PackageIdentifier (PackageName "Cabal") cabalVersion--currentCompilerId :: PackageIdentifier-currentCompilerId = PackageIdentifier (PackageName System.Info.compilerName)- System.Info.compilerVersion--parseHeader :: ByteString -> (PackageIdentifier, PackageIdentifier)-parseHeader header = case BLC8.words header of- ["Saved", "package", "config", "for", pkgId, "written", "by", cabalId, "using", compId] ->- fromMaybe (throw ConfigStateFileBadHeader) $ do- _ <- simpleParse (BLC8.unpack pkgId) :: Maybe PackageIdentifier- cabalId' <- simpleParse (BLC8.unpack cabalId)- compId' <- simpleParse (BLC8.unpack compId)- return (cabalId', compId')- _ -> throw ConfigStateFileNoHeader--showHeader :: PackageIdentifier -> ByteString-showHeader pkgId = BLC8.unwords- [ "Saved", "package", "config", "for"- , BLC8.pack $ display pkgId- , "written", "by"- , BLC8.pack $ display currentCabalId- , "using"- , BLC8.pack $ display currentCompilerId- ]---- |Check that localBuildInfoFile is up-to-date with respect to the--- .cabal file.-checkPersistBuildConfigOutdated :: FilePath -> FilePath -> IO Bool-checkPersistBuildConfigOutdated distPref pkg_descr_file = do- pkg_descr_file `moreRecentFile` (localBuildInfoFile distPref)---- |@dist\/setup-config@-localBuildInfoFile :: FilePath -> FilePath-localBuildInfoFile distPref = distPref </> "setup-config"---- -------------------------------------------------------------------------------- * Configuration--- --------------------------------------------------------------------------------- |Perform the \"@.\/setup configure@\" action.--- Returns the @.setup-config@ file.-configure :: (GenericPackageDescription, HookedBuildInfo)- -> ConfigFlags -> IO LocalBuildInfo-configure (pkg_descr0, pbi) cfg- = do let distPref = fromFlag (configDistPref cfg)- buildDir' = distPref </> "build"- verbosity = fromFlag (configVerbosity cfg)-- setupMessage verbosity "Configuring" (packageId pkg_descr0)-- unless (configLibCoverage cfg == NoFlag) $ do- let enable | fromFlag (configLibCoverage cfg) = "enable"- | otherwise = "disable"- warn verbosity- ("The flag --" ++ enable ++ "-library-coverage is deprecated. "- ++ "Please use --" ++ enable ++ "-coverage instead.")-- createDirectoryIfMissingVerbose (lessVerbose verbosity) True distPref-- let programsConfig = mkProgramsConfig cfg (configPrograms cfg)- userInstall = fromFlag (configUserInstall cfg)- packageDbs = interpretPackageDbFlags userInstall- (configPackageDBs cfg)-- -- detect compiler- (comp, compPlatform, programsConfig') <- configCompilerEx- (flagToMaybe $ configHcFlavor cfg)- (flagToMaybe $ configHcPath cfg) (flagToMaybe $ configHcPkg cfg)- programsConfig (lessVerbose verbosity)- let version = compilerVersion comp- flavor = compilerFlavor comp-- -- Create a PackageIndex that makes *any libraries that might be*- -- defined internally to this package look like installed packages, in- -- case an executable should refer to any of them as dependencies.- --- -- It must be *any libraries that might be* defined rather than the- -- actual definitions, because these depend on conditionals in the .cabal- -- file, and we haven't resolved them yet. finalizePackageDescription- -- does the resolution of conditionals, and it takes internalPackageSet- -- as part of its input.- --- -- Currently a package can define no more than one library (which has- -- the same name as the package) but we could extend this later.- -- If we later allowed private internal libraries, then here we would- -- need to pre-scan the conditional data to make a list of all private- -- libraries that could possibly be defined by the .cabal file.- let pid = packageId pkg_descr0- internalPackage = emptyInstalledPackageInfo {- --TODO: should use a per-compiler method to map the source- -- package ID into an installed package id we can use- -- for the internal package set. The open-codes use of- -- InstalledPackageId . display here is a hack.- Installed.installedPackageId =- InstalledPackageId $ display $ pid,- Installed.sourcePackageId = pid- }- internalPackageSet = PackageIndex.fromList [internalPackage]- installedPackageSet <- getInstalledPackages (lessVerbose verbosity) comp- packageDbs programsConfig'-- (allConstraints, requiredDepsMap) <- either die return $- combinedConstraints (configConstraints cfg)- (configDependencies cfg)- installedPackageSet-- let exactConf = fromFlagOrDefault False (configExactConfiguration cfg)- -- Constraint test function for the solver- dependencySatisfiable d@(Dependency depName verRange)- | exactConf =- -- When we're given '--exact-configuration', we assume that all- -- dependencies and flags are exactly specified on the command- -- line. Thus we only consult the 'requiredDepsMap'. Note that- -- we're not doing the version range check, so if there's some- -- dependency that wasn't specified on the command line,- -- 'finalizePackageDescription' will fail.- --- -- TODO: mention '--exact-configuration' in the error message- -- when this fails?- (depName `Map.member` requiredDepsMap) || isInternalDep-- | otherwise =- -- Normal operation: just look up dependency in the package- -- index.- not . null . PackageIndex.lookupDependency pkgs' $ d- where- pkgs' = PackageIndex.insert internalPackage installedPackageSet- isInternalDep = pkgName pid == depName- && pkgVersion pid `withinRange` verRange- enableTest t = t { testEnabled = fromFlag (configTests cfg) }- flaggedTests = map (\(n, t) -> (n, mapTreeData enableTest t))- (condTestSuites pkg_descr0)- enableBenchmark bm = bm { benchmarkEnabled =- fromFlag (configBenchmarks cfg) }- flaggedBenchmarks = map (\(n, bm) ->- (n, mapTreeData enableBenchmark bm))- (condBenchmarks pkg_descr0)- pkg_descr0'' = pkg_descr0 { condTestSuites = flaggedTests- , condBenchmarks = flaggedBenchmarks }-- (pkg_descr0', flags) <-- case finalizePackageDescription- (configConfigurationsFlags cfg)- dependencySatisfiable- compPlatform- (compilerInfo comp)- allConstraints- pkg_descr0''- of Right r -> return r- Left missing ->- die $ "At least the following dependencies are missing:\n"- ++ (render . nest 4 . sep . punctuate comma- . map (disp . simplifyDependency)- $ missing)-- -- Sanity check: if '--exact-configuration' was given, ensure that the- -- complete flag assignment was specified on the command line.- when exactConf $ do- let cmdlineFlags = map fst (configConfigurationsFlags cfg)- allFlags = map flagName . genPackageFlags $ pkg_descr0- diffFlags = allFlags \\ cmdlineFlags- when (not . null $ diffFlags) $- die $ "'--exact-conf' was given, "- ++ "but the following flags were not specified: "- ++ intercalate ", " (map show diffFlags)-- -- add extra include/lib dirs as specified in cfg- -- we do it here so that those get checked too- let pkg_descr = addExtraIncludeLibDirs pkg_descr0'-- unless (renamingPackageFlagsSupported comp ||- and [ rn == defaultRenaming- | bi <- allBuildInfo pkg_descr- , rn <- Map.elems (targetBuildRenaming bi)]) $- die $ "Your compiler does not support thinning and renaming on "- ++ "package flags. To use this feature you probably must use "- ++ "GHC 7.9 or later."-- when (not (null flags)) $- info verbosity $ "Flags chosen: "- ++ intercalate ", " [ name ++ "=" ++ display value- | (FlagName name, value) <- flags ]-- when (maybe False (not.null.PD.reexportedModules) (PD.library pkg_descr)- && not (reexportedModulesSupported comp)) $ do- die $ "Your compiler does not support module re-exports. To use "- ++ "this feature you probably must use GHC 7.9 or later."-- checkPackageProblems verbosity pkg_descr0- (updatePackageDescription pbi pkg_descr)-- -- Handle hole instantiation- (holeDeps, hole_insts) <- configureInstantiateWith pkg_descr cfg installedPackageSet-- let selectDependencies :: [Dependency] ->- ([FailedDependency], [ResolvedDependency])- selectDependencies =- (\xs -> ([ x | Left x <- xs ], [ x | Right x <- xs ]))- . map (selectDependency internalPackageSet installedPackageSet- requiredDepsMap)-- (failedDeps, allPkgDeps) =- selectDependencies (buildDepends pkg_descr)-- internalPkgDeps = [ pkgid- | InternalDependency _ pkgid <- allPkgDeps ]- externalPkgDeps = [ pkg- | ExternalDependency _ pkg <- allPkgDeps ]-- when (not (null internalPkgDeps)- && not (newPackageDepsBehaviour pkg_descr)) $- die $ "The field 'build-depends: "- ++ intercalate ", " (map (display . packageName) internalPkgDeps)- ++ "' refers to a library which is defined within the same "- ++ "package. To use this feature the package must specify at "- ++ "least 'cabal-version: >= 1.8'."-- reportFailedDependencies failedDeps- reportSelectedDependencies verbosity allPkgDeps-- let installDeps = Map.elems- . Map.fromList- . map (\v -> (Installed.installedPackageId v, v))- $ externalPkgDeps ++ holeDeps-- packageDependsIndex <-- case PackageIndex.dependencyClosure installedPackageSet- (map Installed.installedPackageId installDeps) of- Left packageDependsIndex -> return packageDependsIndex- Right broken ->- die $ "The following installed packages are broken because other"- ++ " packages they depend on are missing. These broken "- ++ "packages must be rebuilt before they can be used.\n"- ++ unlines [ "package "- ++ display (packageId pkg)- ++ " is broken due to missing package "- ++ intercalate ", " (map display deps)- | (pkg, deps) <- broken ]-- let pseudoTopPkg = emptyInstalledPackageInfo {- Installed.installedPackageId =- InstalledPackageId (display (packageId pkg_descr)),- Installed.sourcePackageId = packageId pkg_descr,- Installed.depends =- map Installed.installedPackageId installDeps- }- case PackageIndex.dependencyInconsistencies- . PackageIndex.insert pseudoTopPkg- $ packageDependsIndex of- [] -> return ()- inconsistencies ->- warn verbosity $- "This package indirectly depends on multiple versions of the same "- ++ "package. This is highly likely to cause a compile failure.\n"- ++ unlines [ "package " ++ display pkg ++ " requires "- ++ display (PackageIdentifier name ver)- | (name, uses) <- inconsistencies- , (pkg, ver) <- uses ]-- -- Calculate the package key. We're going to store it in LocalBuildInfo- -- canonically, but ComponentsLocalBuildInfo also needs to know about it- -- XXX Do we need the internal deps?- -- NB: does *not* include holeDeps!- let pkg_key = mkPackageKey (packageKeySupported comp)- (package pkg_descr)- (map Installed.packageKey externalPkgDeps)- (map (\(k,(p,m)) -> (k,(Installed.packageKey p,m))) hole_insts)-- -- internal component graph- buildComponents <-- case mkComponentsGraph pkg_descr internalPkgDeps of- Left componentCycle -> reportComponentCycle componentCycle- Right components ->- case mkComponentsLocalBuildInfo packageDependsIndex pkg_descr- internalPkgDeps externalPkgDeps holeDeps- (Map.fromList hole_insts)- pkg_key components of- Left problems -> reportModuleReexportProblems problems- Right components' -> return components'-- -- installation directories- defaultDirs <- defaultInstallDirs flavor userInstall (hasLibs pkg_descr)- let installDirs = combineInstallDirs fromFlagOrDefault- defaultDirs (configInstallDirs cfg)-- -- check languages and extensions- let langlist = nub $ catMaybes $ map defaultLanguage- (allBuildInfo pkg_descr)- let langs = unsupportedLanguages comp langlist- when (not (null langs)) $- die $ "The package " ++ display (packageId pkg_descr0)- ++ " requires the following languages which are not "- ++ "supported by " ++ display (compilerId comp) ++ ": "- ++ intercalate ", " (map display langs)- let extlist = nub $ concatMap allExtensions (allBuildInfo pkg_descr)- let exts = unsupportedExtensions comp extlist- when (not (null exts)) $- die $ "The package " ++ display (packageId pkg_descr0)- ++ " requires the following language extensions which are not "- ++ "supported by " ++ display (compilerId comp) ++ ": "- ++ intercalate ", " (map display exts)-- -- configured known/required programs & external build tools- -- exclude build-tool deps on "internal" exes in the same package- let requiredBuildTools =- [ buildTool- | let exeNames = map exeName (executables pkg_descr)- , bi <- allBuildInfo pkg_descr- , buildTool@(Dependency (PackageName toolName) reqVer)- <- buildTools bi- , let isInternal =- toolName `elem` exeNames- -- we assume all internal build-tools are- -- versioned with the package:- && packageVersion pkg_descr `withinRange` reqVer- , not isInternal ]-- programsConfig'' <-- configureAllKnownPrograms (lessVerbose verbosity) programsConfig'- >>= configureRequiredPrograms verbosity requiredBuildTools-- (pkg_descr', programsConfig''') <-- configurePkgconfigPackages verbosity pkg_descr programsConfig''-- split_objs <-- if not (fromFlag $ configSplitObjs cfg)- then return False- else case flavor of- GHC | version >= Version [6,5] [] -> return True- GHCJS -> return True- _ -> do warn verbosity- ("this compiler does not support " ++- "--enable-split-objs; ignoring")- return False-- let ghciLibByDefault =- case compilerId comp of- CompilerId GHC _ ->- -- If ghc is non-dynamic, then ghci needs object files,- -- so we build one by default.- --- -- Technically, archive files should be sufficient for ghci,- -- but because of GHC bug #8942, it has never been safe to- -- rely on them. By the time that bug was fixed, ghci had- -- been changed to read shared libraries instead of archive- -- files (see next code block).- not (GHC.isDynamic comp)- CompilerId GHCJS _ ->- not (GHCJS.isDynamic comp)- _ -> False-- let sharedLibsByDefault- | fromFlag (configDynExe cfg) =- -- build a shared library if dynamically-linked- -- executables are requested- True- | otherwise = case compilerId comp of- CompilerId GHC _ ->- -- if ghc is dynamic, then ghci needs a shared- -- library, so we build one by default.- GHC.isDynamic comp- CompilerId GHCJS _ ->- GHCJS.isDynamic comp- _ -> False- withSharedLib_ =- -- build shared libraries if required by GHC or by the- -- executable linking mode, but allow the user to force- -- building only static library archives with- -- --disable-shared.- fromFlagOrDefault sharedLibsByDefault $ configSharedLib cfg- withDynExe_ = fromFlag $ configDynExe cfg- when (withDynExe_ && not withSharedLib_) $ warn verbosity $- "Executables will use dynamic linking, but a shared library "- ++ "is not being built. Linking will fail if any executables "- ++ "depend on the library."-- let withProfExe_ = fromFlagOrDefault False $ configProfExe cfg- withProfLib_ = fromFlagOrDefault withProfExe_ $ configProfLib cfg- when (withProfExe_ && not withProfLib_) $ warn verbosity $- "Executables will be built with profiling, but library "- ++ "profiling is disabled. Linking will fail if any executables "- ++ "depend on the library."-- let configCoverage_ =- mappend (configCoverage cfg) (configLibCoverage cfg)-- cfg' = cfg { configCoverage = configCoverage_ }-- reloc <-- if not (fromFlag $ configRelocatable cfg)- then return False- else return True-- let lbi = LocalBuildInfo {- configFlags = cfg',- extraConfigArgs = [], -- Currently configure does not- -- take extra args, but if it- -- did they would go here.- installDirTemplates = installDirs,- compiler = comp,- hostPlatform = compPlatform,- buildDir = buildDir',- componentsConfigs = buildComponents,- installedPkgs = packageDependsIndex,- pkgDescrFile = Nothing,- localPkgDescr = pkg_descr',- pkgKey = pkg_key,- instantiatedWith = hole_insts,- withPrograms = programsConfig''',- withVanillaLib = fromFlag $ configVanillaLib cfg,- withProfLib = withProfLib_,- withSharedLib = withSharedLib_,- withDynExe = withDynExe_,- withProfExe = withProfExe_,- withOptimization = fromFlag $ configOptimization cfg,- withDebugInfo = fromFlag $ configDebugInfo cfg,- withGHCiLib = fromFlagOrDefault ghciLibByDefault $- configGHCiLib cfg,- splitObjs = split_objs,- stripExes = fromFlag $ configStripExes cfg,- stripLibs = fromFlag $ configStripLibs cfg,- withPackageDB = packageDbs,- progPrefix = fromFlag $ configProgPrefix cfg,- progSuffix = fromFlag $ configProgSuffix cfg,- relocatable = reloc- }-- when reloc (checkRelocatable verbosity pkg_descr lbi)-- let dirs = absoluteInstallDirs pkg_descr lbi NoCopyDest- relative = prefixRelativeInstallDirs (packageId pkg_descr) lbi-- unless (isAbsolute (prefix dirs)) $ die $- "expected an absolute directory name for --prefix: " ++ prefix dirs-- info verbosity $ "Using " ++ display currentCabalId- ++ " compiled by " ++ display currentCompilerId- info verbosity $ "Using compiler: " ++ showCompilerId comp- info verbosity $ "Using install prefix: " ++ prefix dirs-- let dirinfo name dir isPrefixRelative =- info verbosity $ name ++ " installed in: " ++ dir ++ relNote- where relNote = case buildOS of- Windows | not (hasLibs pkg_descr)- && isNothing isPrefixRelative- -> " (fixed location)"- _ -> ""-- dirinfo "Binaries" (bindir dirs) (bindir relative)- dirinfo "Libraries" (libdir dirs) (libdir relative)- dirinfo "Private binaries" (libexecdir dirs) (libexecdir relative)- dirinfo "Data files" (datadir dirs) (datadir relative)- dirinfo "Documentation" (docdir dirs) (docdir relative)- dirinfo "Configuration files" (sysconfdir dirs) (sysconfdir relative)-- sequence_ [ reportProgram verbosity prog configuredProg- | (prog, configuredProg) <- knownPrograms programsConfig''' ]-- return lbi-- where- addExtraIncludeLibDirs pkg_descr =- let extraBi = mempty { extraLibDirs = configExtraLibDirs cfg- , PD.includeDirs = configExtraIncludeDirs cfg}- modifyLib l = l{ libBuildInfo = libBuildInfo l- `mappend` extraBi }- modifyExecutable e = e{ buildInfo = buildInfo e- `mappend` extraBi}- in pkg_descr{ library = modifyLib `fmap` library pkg_descr- , executables = modifyExecutable `map`- executables pkg_descr}--mkProgramsConfig :: ConfigFlags -> ProgramConfiguration -> ProgramConfiguration-mkProgramsConfig cfg initialProgramsConfig = programsConfig- where- programsConfig = userSpecifyArgss (configProgramArgs cfg)- . userSpecifyPaths (configProgramPaths cfg)- . setProgramSearchPath searchpath- $ initialProgramsConfig- searchpath = getProgramSearchPath (initialProgramsConfig)- ++ map ProgramSearchPathDir (fromNubList $ configProgramPathExtra cfg)---- -------------------------------------------------------------------------------- Configuring package dependencies--reportProgram :: Verbosity -> Program -> Maybe ConfiguredProgram -> IO ()-reportProgram verbosity prog Nothing- = info verbosity $ "No " ++ programName prog ++ " found"-reportProgram verbosity prog (Just configuredProg)- = info verbosity $ "Using " ++ programName prog ++ version ++ location- where location = case programLocation configuredProg of- FoundOnSystem p -> " found on system at: " ++ p- UserSpecified p -> " given by user at: " ++ p- version = case programVersion configuredProg of- Nothing -> ""- Just v -> " version " ++ display v--hackageUrl :: String-hackageUrl = "http://hackage.haskell.org/package/"--data ResolvedDependency = ExternalDependency Dependency InstalledPackageInfo- | InternalDependency Dependency PackageId -- should be a- -- lib name--data FailedDependency = DependencyNotExists PackageName- | DependencyNoVersion Dependency---- | Test for a package dependency and record the version we have installed.-selectDependency :: InstalledPackageIndex -- ^ Internally defined packages- -> InstalledPackageIndex -- ^ Installed packages- -> Map PackageName InstalledPackageInfo- -- ^ Packages for which we have been given specific deps to use- -> Dependency- -> Either FailedDependency ResolvedDependency-selectDependency internalIndex installedIndex requiredDepsMap- dep@(Dependency pkgname vr) =- -- If the dependency specification matches anything in the internal package- -- index, then we prefer that match to anything in the second.- -- For example:- --- -- Name: MyLibrary- -- Version: 0.1- -- Library- -- ..- -- Executable my-exec- -- build-depends: MyLibrary- --- -- We want "build-depends: MyLibrary" always to match the internal library- -- even if there is a newer installed library "MyLibrary-0.2".- -- However, "build-depends: MyLibrary >= 0.2" should match the installed one.- case PackageIndex.lookupPackageName internalIndex pkgname of- [(_,[pkg])] | packageVersion pkg `withinRange` vr- -> Right $ InternalDependency dep (packageId pkg)-- _ -> case Map.lookup pkgname requiredDepsMap of- -- If we know the exact pkg to use, then use it.- Just pkginstance -> Right (ExternalDependency dep pkginstance)- -- Otherwise we just pick an arbitrary instance of the latest version.- Nothing -> case PackageIndex.lookupDependency installedIndex dep of- [] -> Left $ DependencyNotExists pkgname- pkgs -> Right $ ExternalDependency dep $- case last pkgs of- (_ver, pkginstances) -> head pkginstances--reportSelectedDependencies :: Verbosity- -> [ResolvedDependency] -> IO ()-reportSelectedDependencies verbosity deps =- info verbosity $ unlines- [ "Dependency " ++ display (simplifyDependency dep)- ++ ": using " ++ display pkgid- | resolved <- deps- , let (dep, pkgid) = case resolved of- ExternalDependency dep' pkg' -> (dep', packageId pkg')- InternalDependency dep' pkgid' -> (dep', pkgid') ]--reportFailedDependencies :: [FailedDependency] -> IO ()-reportFailedDependencies [] = return ()-reportFailedDependencies failed =- die (intercalate "\n\n" (map reportFailedDependency failed))-- where- reportFailedDependency (DependencyNotExists pkgname) =- "there is no version of " ++ display pkgname ++ " installed.\n"- ++ "Perhaps you need to download and install it from\n"- ++ hackageUrl ++ display pkgname ++ "?"-- reportFailedDependency (DependencyNoVersion dep) =- "cannot satisfy dependency " ++ display (simplifyDependency dep) ++ "\n"--getInstalledPackages :: Verbosity -> Compiler- -> PackageDBStack -> ProgramConfiguration- -> IO InstalledPackageIndex-getInstalledPackages verbosity comp packageDBs progconf = do- when (null packageDBs) $- die $ "No package databases have been specified. If you use "- ++ "--package-db=clear, you must follow it with --package-db= "- ++ "with 'global', 'user' or a specific file."-- info verbosity "Reading installed packages..."- case compilerFlavor comp of- GHC -> GHC.getInstalledPackages verbosity packageDBs progconf- GHCJS -> GHCJS.getInstalledPackages verbosity packageDBs progconf- JHC -> JHC.getInstalledPackages verbosity packageDBs progconf- LHC -> LHC.getInstalledPackages verbosity packageDBs progconf- UHC -> UHC.getInstalledPackages verbosity comp packageDBs progconf- HaskellSuite {} ->- HaskellSuite.getInstalledPackages verbosity packageDBs progconf- flv -> die $ "don't know how to find the installed packages for "- ++ display flv---- | Like 'getInstalledPackages', but for a single package DB.-getPackageDBContents :: Verbosity -> Compiler- -> PackageDB -> ProgramConfiguration- -> IO InstalledPackageIndex-getPackageDBContents verbosity comp packageDB progconf = do- info verbosity "Reading installed packages..."- case compilerFlavor comp of- GHC -> GHC.getPackageDBContents verbosity packageDB progconf- GHCJS -> GHCJS.getPackageDBContents verbosity packageDB progconf- -- For other compilers, try to fall back on 'getInstalledPackages'.- _ -> getInstalledPackages verbosity comp [packageDB] progconf----- | The user interface specifies the package dbs to use with a combination of--- @--global@, @--user@ and @--package-db=global|user|clear|$file@.--- This function combines the global/user flag and interprets the package-db--- flag into a single package db stack.----interpretPackageDbFlags :: Bool -> [Maybe PackageDB] -> PackageDBStack-interpretPackageDbFlags userInstall specificDBs =- extra initialStack specificDBs- where- initialStack | userInstall = [GlobalPackageDB, UserPackageDB]- | otherwise = [GlobalPackageDB]-- extra dbs' [] = dbs'- extra _ (Nothing:dbs) = extra [] dbs- extra dbs' (Just db:dbs) = extra (dbs' ++ [db]) dbs--newPackageDepsBehaviourMinVersion :: Version-newPackageDepsBehaviourMinVersion = Version [1,7,1] []---- In older cabal versions, there was only one set of package dependencies for--- the whole package. In this version, we can have separate dependencies per--- target, but we only enable this behaviour if the minimum cabal version--- specified is >= a certain minimum. Otherwise, for compatibility we use the--- old behaviour.-newPackageDepsBehaviour :: PackageDescription -> Bool-newPackageDepsBehaviour pkg =- specVersion pkg >= newPackageDepsBehaviourMinVersion---- We are given both --constraint="foo < 2.0" style constraints and also--- specific packages to pick via --dependency="foo=foo-2.0-177d5cdf20962d0581".------ When finalising the package we have to take into account the specific--- installed deps we've been given, and the finalise function expects--- constraints, so we have to translate these deps into version constraints.------ But after finalising we then have to make sure we pick the right specific--- deps in the end. So we still need to remember which installed packages to--- pick.-combinedConstraints :: [Dependency] ->- [(PackageName, InstalledPackageId)] ->- InstalledPackageIndex ->- Either String ([Dependency],- Map PackageName InstalledPackageInfo)-combinedConstraints constraints dependencies installedPackages = do-- when (not (null badInstalledPackageIds)) $- Left $ render $ text "The following package dependencies were requested"- $+$ nest 4 (dispDependencies badInstalledPackageIds)- $+$ text "however the given installed package instance does not exist."-- when (not (null badNames)) $- Left $ render $ text "The following package dependencies were requested"- $+$ nest 4 (dispDependencies badNames)- $+$ text "however the installed package's name does not match the name given."-- --TODO: we don't check that all dependencies are used!-- return (allConstraints, idConstraintMap)-- where- allConstraints :: [Dependency]- allConstraints = constraints- ++ [ thisPackageVersion (packageId pkg)- | (_, _, Just pkg) <- dependenciesPkgInfo ]-- idConstraintMap :: Map PackageName InstalledPackageInfo- idConstraintMap = Map.fromList- [ (packageName pkg, pkg)- | (_, _, Just pkg) <- dependenciesPkgInfo ]-- -- The dependencies along with the installed package info, if it exists- dependenciesPkgInfo :: [(PackageName, InstalledPackageId,- Maybe InstalledPackageInfo)]- dependenciesPkgInfo =- [ (pkgname, ipkgid, mpkg)- | (pkgname, ipkgid) <- dependencies- , let mpkg = PackageIndex.lookupInstalledPackageId- installedPackages ipkgid- ]-- -- If we looked up a package specified by an installed package id- -- (i.e. someone has written a hash) and didn't find it then it's- -- an error.- badInstalledPackageIds =- [ (pkgname, ipkgid)- | (pkgname, ipkgid, Nothing) <- dependenciesPkgInfo ]-- -- If someone has written e.g.- -- --dependency="foo=MyOtherLib-1.0-07...5bf30" then they have- -- probably made a mistake.- badNames =- [ (requestedPkgName, ipkgid)- | (requestedPkgName, ipkgid, Just pkg) <- dependenciesPkgInfo- , let foundPkgName = packageName pkg- , requestedPkgName /= foundPkgName ]-- dispDependencies deps =- hsep [ text "--dependency="- <> quotes (disp pkgname <> char '=' <> disp ipkgid)- | (pkgname, ipkgid) <- deps ]---- -------------------------------------------------------------------------------- Configuring hole instantiation--configureInstantiateWith :: PackageDescription- -> ConfigFlags- -> InstalledPackageIndex -- ^ installed packages- -> IO ([InstalledPackageInfo],- [(ModuleName, (InstalledPackageInfo, ModuleName))])-configureInstantiateWith pkg_descr cfg installedPackageSet = do- -- Holes: First, check and make sure the provided instantiation covers- -- all the holes we know about. Indefinite package installation is- -- not handled at all at this point.- -- NB: We union together /all/ of the requirements when calculating- -- the package key.- -- NB: For now, we assume that dependencies don't contribute signatures.- -- This will be handled by cabal-install; as far as ./Setup is- -- concerned, the most important thing is to be provided correctly- -- built dependencies.- let signatures =- maybe [] (\lib -> requiredSignatures lib ++ exposedSignatures lib)- (PD.library pkg_descr)- signatureSet = Set.fromList signatures- instantiateMap = Map.fromList (configInstantiateWith cfg)- missing_impls = filter (not . flip Map.member instantiateMap) signatures- hole_insts0 = filter (\(k,_) -> Set.member k signatureSet) (configInstantiateWith cfg)-- when (not (null missing_impls)) $- die $ "Missing signature implementations for these modules: "- ++ intercalate ", " (map display missing_impls)-- -- Holes: Next, we need to make sure we have packages to actually- -- provide the implementations we're talking about. This is on top- -- of the normal dependency resolution process.- -- TODO: internal dependencies (e.g. the test package depending on the- -- main library) is not currently supported- let selectHoleDependency (k,(i,m)) =- case PackageIndex.lookupInstalledPackageId installedPackageSet i of- Just pkginst -> Right (k,(pkginst, m))- Nothing -> Left i- (failed_hmap, hole_insts) = partitionEithers (map selectHoleDependency hole_insts0)- holeDeps = map (fst.snd) hole_insts -- could have dups-- -- Holes: Finally, any dependencies selected this way have to be- -- included in the allPkgs index, as well as the buildComponents.- -- But don't report these as potential inconsistencies!-- when (not (null failed_hmap)) $- die $ "Could not resolve these package IDs (from signature implementations): "- ++ intercalate ", " (map display failed_hmap)-- return (holeDeps, hole_insts)---- -------------------------------------------------------------------------------- Configuring program dependencies--configureRequiredPrograms :: Verbosity -> [Dependency] -> ProgramConfiguration- -> IO ProgramConfiguration-configureRequiredPrograms verbosity deps conf =- foldM (configureRequiredProgram verbosity) conf deps--configureRequiredProgram :: Verbosity -> ProgramConfiguration -> Dependency- -> IO ProgramConfiguration-configureRequiredProgram verbosity conf- (Dependency (PackageName progName) verRange) =- case lookupKnownProgram progName conf of- Nothing -> die ("Unknown build tool " ++ progName)- Just prog- -- requireProgramVersion always requires the program have a version- -- but if the user says "build-depends: foo" ie no version constraint- -- then we should not fail if we cannot discover the program version.- | verRange == anyVersion -> do- (_, conf') <- requireProgram verbosity prog conf- return conf'- | otherwise -> do- (_, _, conf') <- requireProgramVersion verbosity prog verRange conf- return conf'---- -------------------------------------------------------------------------------- Configuring pkg-config package dependencies--configurePkgconfigPackages :: Verbosity -> PackageDescription- -> ProgramConfiguration- -> IO (PackageDescription, ProgramConfiguration)-configurePkgconfigPackages verbosity pkg_descr conf- | null allpkgs = return (pkg_descr, conf)- | otherwise = do- (_, _, conf') <- requireProgramVersion- (lessVerbose verbosity) pkgConfigProgram- (orLaterVersion $ Version [0,9,0] []) conf- mapM_ requirePkg allpkgs- lib' <- mapM addPkgConfigBILib (library pkg_descr)- exes' <- mapM addPkgConfigBIExe (executables pkg_descr)- tests' <- mapM addPkgConfigBITest (testSuites pkg_descr)- benches' <- mapM addPkgConfigBIBench (benchmarks pkg_descr)- let pkg_descr' = pkg_descr { library = lib', executables = exes',- testSuites = tests', benchmarks = benches' }- return (pkg_descr', conf')-- where- allpkgs = concatMap pkgconfigDepends (allBuildInfo pkg_descr)- pkgconfig = rawSystemProgramStdoutConf (lessVerbose verbosity)- pkgConfigProgram conf-- requirePkg dep@(Dependency (PackageName pkg) range) = do- version <- pkgconfig ["--modversion", pkg]- `catchIO` (\_ -> die notFound)- `catchExit` (\_ -> die notFound)- case simpleParse version of- Nothing -> die "parsing output of pkg-config --modversion failed"- Just v | not (withinRange v range) -> die (badVersion v)- | otherwise -> info verbosity (depSatisfied v)- where- notFound = "The pkg-config package '" ++ pkg ++ "'"- ++ versionRequirement- ++ " is required but it could not be found."- badVersion v = "The pkg-config package '" ++ pkg ++ "'"- ++ versionRequirement- ++ " is required but the version installed on the"- ++ " system is version " ++ display v- depSatisfied v = "Dependency " ++ display dep- ++ ": using version " ++ display v-- versionRequirement- | isAnyVersion range = ""- | otherwise = " version " ++ display range-- -- Adds pkgconfig dependencies to the build info for a component- addPkgConfigBI compBI setCompBI comp = do- bi <- pkgconfigBuildInfo (pkgconfigDepends (compBI comp))- return $ setCompBI comp (compBI comp `mappend` bi)-- -- Adds pkgconfig dependencies to the build info for a library- addPkgConfigBILib = addPkgConfigBI libBuildInfo $- \lib bi -> lib { libBuildInfo = bi }-- -- Adds pkgconfig dependencies to the build info for an executable- addPkgConfigBIExe = addPkgConfigBI buildInfo $- \exe bi -> exe { buildInfo = bi }-- -- Adds pkgconfig dependencies to the build info for a test suite- addPkgConfigBITest = addPkgConfigBI testBuildInfo $- \test bi -> test { testBuildInfo = bi }-- -- Adds pkgconfig dependencies to the build info for a benchmark- addPkgConfigBIBench = addPkgConfigBI benchmarkBuildInfo $- \bench bi -> bench { benchmarkBuildInfo = bi }-- pkgconfigBuildInfo :: [Dependency] -> IO BuildInfo- pkgconfigBuildInfo [] = return mempty- pkgconfigBuildInfo pkgdeps = do- let pkgs = nub [ display pkg | Dependency pkg _ <- pkgdeps ]- ccflags <- pkgconfig ("--cflags" : pkgs)- ldflags <- pkgconfig ("--libs" : pkgs)- return (ccLdOptionsBuildInfo (words ccflags) (words ldflags))---- | Makes a 'BuildInfo' from C compiler and linker flags.------ This can be used with the output from configuration programs like pkg-config--- and similar package-specific programs like mysql-config, freealut-config etc.--- For example:------ > ccflags <- rawSystemProgramStdoutConf verbosity prog conf ["--cflags"]--- > ldflags <- rawSystemProgramStdoutConf verbosity prog conf ["--libs"]--- > return (ccldOptionsBuildInfo (words ccflags) (words ldflags))----ccLdOptionsBuildInfo :: [String] -> [String] -> BuildInfo-ccLdOptionsBuildInfo cflags ldflags =- let (includeDirs', cflags') = partition ("-I" `isPrefixOf`) cflags- (extraLibs', ldflags') = partition ("-l" `isPrefixOf`) ldflags- (extraLibDirs', ldflags'') = partition ("-L" `isPrefixOf`) ldflags'- in mempty {- PD.includeDirs = map (drop 2) includeDirs',- PD.extraLibs = map (drop 2) extraLibs',- PD.extraLibDirs = map (drop 2) extraLibDirs',- PD.ccOptions = cflags',- PD.ldOptions = ldflags''- }---- -------------------------------------------------------------------------------- Determining the compiler details--configCompilerAuxEx :: ConfigFlags- -> IO (Compiler, Platform, ProgramConfiguration)-configCompilerAuxEx cfg = configCompilerEx (flagToMaybe $ configHcFlavor cfg)- (flagToMaybe $ configHcPath cfg)- (flagToMaybe $ configHcPkg cfg)- programsConfig- (fromFlag (configVerbosity cfg))- where- programsConfig = mkProgramsConfig cfg defaultProgramConfiguration--configCompilerEx :: Maybe CompilerFlavor -> Maybe FilePath -> Maybe FilePath- -> ProgramConfiguration -> Verbosity- -> IO (Compiler, Platform, ProgramConfiguration)-configCompilerEx Nothing _ _ _ _ = die "Unknown compiler"-configCompilerEx (Just hcFlavor) hcPath hcPkg conf verbosity = do- (comp, maybePlatform, programsConfig) <- case hcFlavor of- GHC -> GHC.configure verbosity hcPath hcPkg conf- GHCJS -> GHCJS.configure verbosity hcPath hcPkg conf- JHC -> JHC.configure verbosity hcPath hcPkg conf- LHC -> do (_, _, ghcConf) <- GHC.configure verbosity Nothing hcPkg conf- LHC.configure verbosity hcPath Nothing ghcConf- UHC -> UHC.configure verbosity hcPath hcPkg conf- HaskellSuite {} -> HaskellSuite.configure verbosity hcPath hcPkg conf- _ -> die "Unknown compiler"- return (comp, fromMaybe buildPlatform maybePlatform, programsConfig)---- Ideally we would like to not have separate configCompiler* and--- configCompiler*Ex sets of functions, but there are many custom setup scripts--- in the wild that are using them, so the versions with old types are kept for--- backwards compatibility. Platform was added to the return triple in 1.18.--{-# DEPRECATED configCompiler- "'configCompiler' is deprecated. Use 'configCompilerEx' instead." #-}-configCompiler :: Maybe CompilerFlavor -> Maybe FilePath -> Maybe FilePath- -> ProgramConfiguration -> Verbosity- -> IO (Compiler, ProgramConfiguration)-configCompiler mFlavor hcPath hcPkg conf verbosity =- fmap (\(a,_,b) -> (a,b)) $ configCompilerEx mFlavor hcPath hcPkg conf verbosity--{-# DEPRECATED configCompilerAux- "configCompilerAux is deprecated. Use 'configCompilerAuxEx' instead." #-}-configCompilerAux :: ConfigFlags- -> IO (Compiler, ProgramConfiguration)-configCompilerAux = fmap (\(a,_,b) -> (a,b)) . configCompilerAuxEx---- -------------------------------------------------------------------------------- Making the internal component graph---mkComponentsGraph :: PackageDescription- -> [PackageId]- -> Either [ComponentName]- [(Component, [ComponentName])]-mkComponentsGraph pkg_descr internalPkgDeps =- let graph = [ (c, componentName c, componentDeps c)- | c <- pkgEnabledComponents pkg_descr ]- in case checkComponentsCyclic graph of- Just ccycle -> Left [ cname | (_,cname,_) <- ccycle ]- Nothing -> Right [ (c, cdeps) | (c, _, cdeps) <- graph ]- where- -- The dependencies for the given component- componentDeps component =- [ CExeName toolname | Dependency (PackageName toolname) _- <- buildTools bi- , toolname `elem` map exeName- (executables pkg_descr) ]-- ++ [ CLibName | Dependency pkgname _ <- targetBuildDepends bi- , pkgname `elem` map packageName internalPkgDeps ]- where- bi = componentBuildInfo component--reportComponentCycle :: [ComponentName] -> IO a-reportComponentCycle cnames =- die $ "Components in the package depend on each other in a cyclic way:\n "- ++ intercalate " depends on "- [ "'" ++ showComponentName cname ++ "'"- | cname <- cnames ++ [head cnames] ]--mkComponentsLocalBuildInfo :: InstalledPackageIndex- -> PackageDescription- -> [PackageId] -- internal package deps- -> [InstalledPackageInfo] -- external package deps- -> [InstalledPackageInfo] -- hole package deps- -> Map ModuleName (InstalledPackageInfo, ModuleName)- -> PackageKey- -> [(Component, [ComponentName])]- -> Either [(ModuleReexport, String)] -- errors- [(ComponentName, ComponentLocalBuildInfo,- [ComponentName])] -- ok-mkComponentsLocalBuildInfo installedPackages pkg_descr- internalPkgDeps externalPkgDeps holePkgDeps hole_insts- pkg_key graph =- sequence- [ do clbi <- componentLocalBuildInfo c- return (componentName c, clbi, cdeps)- | (c, cdeps) <- graph ]- where- -- The allPkgDeps contains all the package deps for the whole package- -- but we need to select the subset for this specific component.- -- we just take the subset for the package names this component- -- needs. Note, this only works because we cannot yet depend on two- -- versions of the same package.- componentLocalBuildInfo component =- case component of- CLib lib -> do- let exports = map (\n -> Installed.ExposedModule n Nothing Nothing)- (PD.exposedModules lib)- esigs = map (\n -> Installed.ExposedModule n Nothing- (fmap (\(pkg,m) -> Installed.OriginalModule- (Installed.installedPackageId pkg) m)- (Map.lookup n hole_insts)))- (PD.exposedSignatures lib)- reexports <- resolveModuleReexports installedPackages- (packageId pkg_descr)- externalPkgDeps lib- return LibComponentLocalBuildInfo {- componentPackageDeps = cpds,- componentLibraries = [ LibraryName ("HS" ++ packageKeyLibraryName (package pkg_descr) pkg_key) ],- componentPackageRenaming = cprns,- componentExposedModules = exports ++ reexports ++ esigs- }- CExe _ ->- return ExeComponentLocalBuildInfo {- componentPackageDeps = cpds,- componentPackageRenaming = cprns- }- CTest _ ->- return TestComponentLocalBuildInfo {- componentPackageDeps = cpds,- componentPackageRenaming = cprns- }- CBench _ ->- return BenchComponentLocalBuildInfo {- componentPackageDeps = cpds,- componentPackageRenaming = cprns- }- where- bi = componentBuildInfo component- dedup = Map.toList . Map.fromList- cpds = if newPackageDepsBehaviour pkg_descr- then dedup $- [ (Installed.installedPackageId pkg, packageId pkg)- | pkg <- selectSubset bi externalPkgDeps ]- ++ [ (inplacePackageId pkgid, pkgid)- | pkgid <- selectSubset bi internalPkgDeps ]- ++ [ (Installed.installedPackageId pkg, packageId pkg)- | pkg <- holePkgDeps ]- else [ (Installed.installedPackageId pkg, packageId pkg)- | pkg <- externalPkgDeps ]- cprns = if newPackageDepsBehaviour pkg_descr- then Map.unionWith mappend- -- We need hole dependencies passed to GHC, so add them here- -- (but note that they're fully thinned out. If they- -- appeared legitimately the monoid instance will- -- fill them out.- (Map.fromList [(packageName pkg, mempty) | pkg <- holePkgDeps])- (targetBuildRenaming bi)- -- Hack: if we have old package-deps behavior, it's impossible- -- for non-default renamings to be used, because the Cabal- -- version is too early. This is a good, because while all the- -- deps were bundled up in buildDepends, we didn't do this for- -- renamings, so it's not even clear how to get the merged- -- version. So just assume that all of them are the default..- else Map.fromList (map (\(_,pid) -> (packageName pid, defaultRenaming)) cpds)-- selectSubset :: Package pkg => BuildInfo -> [pkg] -> [pkg]- selectSubset bi pkgs =- [ pkg | pkg <- pkgs, packageName pkg `elem` names bi ]-- names bi = [ name | Dependency name _ <- targetBuildDepends bi ]---- | Given the author-specified re-export declarations from the .cabal file,--- resolve them to the form that we need for the package database.------ An invariant of the package database is that we always link the re-export--- directly to its original defining location (rather than indirectly via a--- chain of re-exporting packages).----resolveModuleReexports :: InstalledPackageIndex- -> PackageId- -> [InstalledPackageInfo]- -> Library- -> Either [(ModuleReexport, String)] -- errors- [Installed.ExposedModule] -- ok-resolveModuleReexports installedPackages srcpkgid externalPkgDeps lib =- case partitionEithers (map resolveModuleReexport (PD.reexportedModules lib)) of- ([], ok) -> Right ok- (errs, _) -> Left errs- where- -- A mapping from visible module names to their original defining- -- module name. We also record the package name of the package which- -- *immediately* provided the module (not the original) to handle if the- -- user explicitly says which build-depends they want to reexport from.- visibleModules :: Map ModuleName [(PackageName, Installed.ExposedModule)]- visibleModules =- Map.fromListWith (++) $- [ (Installed.exposedName exposedModule, [(exportingPackageName,- exposedModule)])- -- The package index here contains all the indirect deps of the- -- package we're configuring, but we want just the direct deps- | let directDeps = Set.fromList (map Installed.installedPackageId externalPkgDeps)- , pkg <- PackageIndex.allPackages installedPackages- , Installed.installedPackageId pkg `Set.member` directDeps- , let exportingPackageName = packageName pkg- , exposedModule <- visibleModuleDetails pkg- ]- ++ [ (visibleModuleName, [(exportingPackageName, exposedModule)])- | visibleModuleName <- PD.exposedModules lib- ++ otherModules (libBuildInfo lib)- , let exportingPackageName = packageName srcpkgid- definingModuleName = visibleModuleName- -- we don't know the InstalledPackageId of this package yet- -- we will fill it in later, before registration.- definingPackageId = InstalledPackageId ""- originalModule = Installed.OriginalModule definingPackageId- definingModuleName- exposedModule = Installed.ExposedModule visibleModuleName- (Just originalModule)- Nothing- ]-- -- All the modules exported from this package and their defining name and- -- package (either defined here in this package or re-exported from some- -- other package). Return an ExposedModule because we want to hold onto- -- signature information.- visibleModuleDetails :: InstalledPackageInfo -> [Installed.ExposedModule]- visibleModuleDetails pkg = do- exposedModule <- Installed.exposedModules pkg- case Installed.exposedReexport exposedModule of- -- The first case is the modules actually defined in this package.- -- In this case the reexport will point to this package.- Nothing -> return exposedModule { Installed.exposedReexport =- Just (Installed.OriginalModule (Installed.installedPackageId pkg)- (Installed.exposedName exposedModule)) }- -- On the other hand, a visible module might actually be itself- -- a re-export! In this case, the re-export info for the package- -- doing the re-export will point us to the original defining- -- module name and package, so we can reuse the entry.- Just _ -> return exposedModule-- resolveModuleReexport reexport@ModuleReexport {- moduleReexportOriginalPackage = moriginalPackageName,- moduleReexportOriginalName = originalName,- moduleReexportName = newName- } =-- let filterForSpecificPackage =- case moriginalPackageName of- Nothing -> id- Just originalPackageName ->- filter (\(pkgname, _) -> pkgname == originalPackageName)-- matches = filterForSpecificPackage- (Map.findWithDefault [] originalName visibleModules)- in- case (matches, moriginalPackageName) of- ((_, exposedModule):rest, _)- -- TODO: Refine this check for signatures- | all (\(_, exposedModule') -> Installed.exposedReexport exposedModule- == Installed.exposedReexport exposedModule') rest- -> Right exposedModule { Installed.exposedName = newName }-- ([], Just originalPackageName)- -> Left $ (,) reexport- $ "The package " ++ display originalPackageName- ++ " does not export a module " ++ display originalName-- ([], Nothing)- -> Left $ (,) reexport- $ "The module " ++ display originalName- ++ " is not exported by any suitable package (this package "- ++ "itself nor any of its 'build-depends' dependencies)."-- (ms, _)- -> Left $ (,) reexport- $ "The module " ++ display originalName ++ " is exported "- ++ "by more than one package ("- ++ intercalate ", " [ display pkgname | (pkgname,_) <- ms ]- ++ ") and so the re-export is ambiguous. The ambiguity can "- ++ "be resolved by qualifying by the package name. The "- ++ "syntax is 'packagename:moduleName [as newname]'."-- -- Note: if in future Cabal allows directly depending on multiple- -- instances of the same package (e.g. backpack) then an additional- -- ambiguity case is possible here: (_, Just originalPackageName)- -- with the module being ambigious despite being qualified by a+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Configure+-- Copyright : Isaac Jones 2003-2005+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This deals with the /configure/ phase. It provides the 'configure' action+-- which is given the package description and configure flags. It then tries+-- to: configure the compiler; resolves any conditionals in the package+-- description; resolve the package dependencies; check if all the extensions+-- used by this package are supported by the compiler; check that all the build+-- tools are available (including version checks if appropriate); checks for+-- any required @pkg-config@ packages (updating the 'BuildInfo' with the+-- results)+--+-- Then based on all this it saves the info in the 'LocalBuildInfo' and writes+-- it out to the @dist\/setup-config@ file. It also displays various details to+-- the user, the amount of information displayed depending on the verbosity+-- level.++module Distribution.Simple.Configure (configure,+ writePersistBuildConfig,+ getConfigStateFile,+ getPersistBuildConfig,+ checkPersistBuildConfigOutdated,+ tryGetPersistBuildConfig,+ maybeGetPersistBuildConfig,+ findDistPref, findDistPrefOrDefault,+ computeComponentId,+ computeCompatPackageKey,+ localBuildInfoFile,+ getInstalledPackages,+ getInstalledPackagesMonitorFiles,+ getPackageDBContents,+ configCompiler, configCompilerAux,+ configCompilerEx, configCompilerAuxEx,+ ccLdOptionsBuildInfo,+ checkForeignDeps,+ interpretPackageDbFlags,+ ConfigStateFileError(..),+ tryGetConfigStateFile,+ platformDefines,+ relaxPackageDeps,+ )+ where++import Distribution.Compiler+import Distribution.Utils.NubList+import Distribution.Simple.Compiler hiding (Flag)+import Distribution.Simple.PreProcess+import Distribution.Package+import qualified Distribution.InstalledPackageInfo as Installed+import Distribution.InstalledPackageInfo (InstalledPackageInfo+ ,emptyInstalledPackageInfo)+import qualified Distribution.Simple.PackageIndex as PackageIndex+import Distribution.Simple.PackageIndex (InstalledPackageIndex)+import Distribution.PackageDescription as PD hiding (Flag)+import Distribution.ModuleName+import Distribution.PackageDescription.Configuration+import Distribution.PackageDescription.Check hiding (doesFileExist)+import Distribution.Simple.Program+import Distribution.Simple.Setup as Setup+import qualified Distribution.Simple.InstallDirs as InstallDirs+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.BuildPaths+import Distribution.Simple.Utils+import Distribution.System+import Distribution.Version+import Distribution.Verbosity++import qualified Distribution.Simple.GHC as GHC+import qualified Distribution.Simple.GHCJS as GHCJS+import qualified Distribution.Simple.JHC as JHC+import qualified Distribution.Simple.LHC as LHC+import qualified Distribution.Simple.UHC as UHC+import qualified Distribution.Simple.HaskellSuite as HaskellSuite++-- Prefer the more generic Data.Traversable.mapM to Prelude.mapM+import Prelude hiding ( mapM )+import Control.Exception+ ( Exception, evaluate, throw, throwIO, try )+import Control.Exception ( ErrorCall )+import Control.Monad+ ( liftM, when, unless, foldM, filterM, mplus )+import Distribution.Compat.Binary ( decodeOrFailIO, encode )+import GHC.Fingerprint ( Fingerprint(..), fingerprintString )+import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy.Char8 as BLC8+import Data.List+ ( (\\), nub, partition, isPrefixOf, inits, stripPrefix )+import Data.Maybe+ ( isNothing, catMaybes, fromMaybe, mapMaybe, isJust )+import Data.Either+ ( partitionEithers )+import qualified Data.Set as Set+import Data.Monoid as Mon ( Monoid(..) )+import qualified Data.Map as Map+import Data.Map (Map)+import Data.Traversable+ ( mapM )+import Data.Typeable+import Data.Char ( chr, isAlphaNum )+import Numeric ( showIntAtBase )+import System.Directory+ ( doesFileExist, createDirectoryIfMissing, getTemporaryDirectory )+import System.FilePath+ ( (</>), isAbsolute )+import qualified System.Info+ ( compilerName, compilerVersion )+import System.IO+ ( hPutStrLn, hClose )+import Distribution.Text+ ( Text(disp), defaultStyle, display, simpleParse )+import Text.PrettyPrint+ ( Doc, (<>), (<+>), ($+$), char, comma, empty, hsep, nest+ , punctuate, quotes, render, renderStyle, sep, text )+import Distribution.Compat.Environment ( lookupEnv )+import Distribution.Compat.Exception ( catchExit, catchIO )++-- | The errors that can be thrown when reading the @setup-config@ file.+data ConfigStateFileError+ = ConfigStateFileNoHeader -- ^ No header found.+ | ConfigStateFileBadHeader -- ^ Incorrect header.+ | ConfigStateFileNoParse -- ^ Cannot parse file contents.+ | ConfigStateFileMissing -- ^ No file!+ | ConfigStateFileBadVersion PackageIdentifier PackageIdentifier+ (Either ConfigStateFileError LocalBuildInfo) -- ^ Mismatched version.+ deriving (Typeable)++-- | Format a 'ConfigStateFileError' as a user-facing error message.+dispConfigStateFileError :: ConfigStateFileError -> Doc+dispConfigStateFileError ConfigStateFileNoHeader =+ text "Saved package config file header is missing."+ <+> text "Re-run the 'configure' command."+dispConfigStateFileError ConfigStateFileBadHeader =+ text "Saved package config file header is corrupt."+ <+> text "Re-run the 'configure' command."+dispConfigStateFileError ConfigStateFileNoParse =+ text "Saved package config file is corrupt."+ <+> text "Re-run the 'configure' command."+dispConfigStateFileError ConfigStateFileMissing =+ text "Run the 'configure' command first."+dispConfigStateFileError (ConfigStateFileBadVersion oldCabal oldCompiler _) =+ text "Saved package config file is outdated:"+ $+$ badCabal $+$ badCompiler+ $+$ text "Re-run the 'configure' command."+ where+ badCabal =+ text "• the Cabal version changed from"+ <+> disp oldCabal <+> "to" <+> disp currentCabalId+ badCompiler+ | oldCompiler == currentCompilerId = empty+ | otherwise =+ text "• the compiler changed from"+ <+> disp oldCompiler <+> "to" <+> disp currentCompilerId++instance Show ConfigStateFileError where+ show = renderStyle defaultStyle . dispConfigStateFileError++instance Exception ConfigStateFileError++-- | Read the 'localBuildInfoFile'. Throw an exception if the file is+-- missing, if the file cannot be read, or if the file was created by an older+-- version of Cabal.+getConfigStateFile :: FilePath -- ^ The file path of the @setup-config@ file.+ -> IO LocalBuildInfo+getConfigStateFile filename = do+ exists <- doesFileExist filename+ unless exists $ throwIO ConfigStateFileMissing+ -- Read the config file into a strict ByteString to avoid problems with+ -- lazy I/O, then convert to lazy because the binary package needs that.+ contents <- BS.readFile filename+ let (header, body) = BLC8.span (/='\n') (BLC8.fromChunks [contents])++ headerParseResult <- try $ evaluate $ parseHeader header+ let (cabalId, compId) =+ case headerParseResult of+ Left (_ :: ErrorCall) -> throw ConfigStateFileBadHeader+ Right x -> x++ let getStoredValue = do+ result <- decodeOrFailIO (BLC8.tail body)+ case result of+ Left _ -> throw ConfigStateFileNoParse+ Right x -> return x+ deferErrorIfBadVersion act+ | cabalId /= currentCabalId = do+ eResult <- try act+ throw $ ConfigStateFileBadVersion cabalId compId eResult+ | otherwise = act+ deferErrorIfBadVersion getStoredValue++-- | Read the 'localBuildInfoFile', returning either an error or the local build+-- info.+tryGetConfigStateFile :: FilePath -- ^ The file path of the @setup-config@ file.+ -> IO (Either ConfigStateFileError LocalBuildInfo)+tryGetConfigStateFile = try . getConfigStateFile++-- | Try to read the 'localBuildInfoFile'.+tryGetPersistBuildConfig :: FilePath -- ^ The @dist@ directory path.+ -> IO (Either ConfigStateFileError LocalBuildInfo)+tryGetPersistBuildConfig = try . getPersistBuildConfig++-- | Read the 'localBuildInfoFile'. Throw an exception if the file is+-- missing, if the file cannot be read, or if the file was created by an older+-- version of Cabal.+getPersistBuildConfig :: FilePath -- ^ The @dist@ directory path.+ -> IO LocalBuildInfo+getPersistBuildConfig = getConfigStateFile . localBuildInfoFile++-- | Try to read the 'localBuildInfoFile'.+maybeGetPersistBuildConfig :: FilePath -- ^ The @dist@ directory path.+ -> IO (Maybe LocalBuildInfo)+maybeGetPersistBuildConfig =+ liftM (either (const Nothing) Just) . tryGetPersistBuildConfig++-- | After running configure, output the 'LocalBuildInfo' to the+-- 'localBuildInfoFile'.+writePersistBuildConfig :: FilePath -- ^ The @dist@ directory path.+ -> LocalBuildInfo -- ^ The 'LocalBuildInfo' to write.+ -> IO ()+writePersistBuildConfig distPref lbi = do+ createDirectoryIfMissing False distPref+ writeFileAtomic (localBuildInfoFile distPref) $+ BLC8.unlines [showHeader pkgId, encode lbi]+ where+ pkgId = packageId $ localPkgDescr lbi++-- | Identifier of the current Cabal package.+currentCabalId :: PackageIdentifier+currentCabalId = PackageIdentifier (PackageName "Cabal") cabalVersion++-- | Identifier of the current compiler package.+currentCompilerId :: PackageIdentifier+currentCompilerId = PackageIdentifier (PackageName System.Info.compilerName)+ System.Info.compilerVersion++-- | Parse the @setup-config@ file header, returning the package identifiers+-- for Cabal and the compiler.+parseHeader :: ByteString -- ^ The file contents.+ -> (PackageIdentifier, PackageIdentifier)+parseHeader header = case BLC8.words header of+ ["Saved", "package", "config", "for", pkgId, "written", "by", cabalId,+ "using", compId] ->+ fromMaybe (throw ConfigStateFileBadHeader) $ do+ _ <- simpleParse (BLC8.unpack pkgId) :: Maybe PackageIdentifier+ cabalId' <- simpleParse (BLC8.unpack cabalId)+ compId' <- simpleParse (BLC8.unpack compId)+ return (cabalId', compId')+ _ -> throw ConfigStateFileNoHeader++-- | Generate the @setup-config@ file header.+showHeader :: PackageIdentifier -- ^ The processed package.+ -> ByteString+showHeader pkgId = BLC8.unwords+ [ "Saved", "package", "config", "for"+ , BLC8.pack $ display pkgId+ , "written", "by"+ , BLC8.pack $ display currentCabalId+ , "using"+ , BLC8.pack $ display currentCompilerId+ ]++-- | Check that localBuildInfoFile is up-to-date with respect to the+-- .cabal file.+checkPersistBuildConfigOutdated :: FilePath -> FilePath -> IO Bool+checkPersistBuildConfigOutdated distPref pkg_descr_file = do+ pkg_descr_file `moreRecentFile` (localBuildInfoFile distPref)++-- | Get the path of @dist\/setup-config@.+localBuildInfoFile :: FilePath -- ^ The @dist@ directory path.+ -> FilePath+localBuildInfoFile distPref = distPref </> "setup-config"++-- -----------------------------------------------------------------------------+-- * Configuration+-- -----------------------------------------------------------------------------++-- | Return the \"dist/\" prefix, or the default prefix. The prefix is taken+-- from (in order of highest to lowest preference) the override prefix, the+-- \"CABAL_BUILDDIR\" environment variable, or the default prefix.+findDistPref :: FilePath -- ^ default \"dist\" prefix+ -> Setup.Flag FilePath -- ^ override \"dist\" prefix+ -> IO FilePath+findDistPref defDistPref overrideDistPref = do+ envDistPref <- liftM parseEnvDistPref (lookupEnv "CABAL_BUILDDIR")+ return $ fromFlagOrDefault defDistPref (mappend envDistPref overrideDistPref)+ where+ parseEnvDistPref env =+ case env of+ Just distPref | not (null distPref) -> toFlag distPref+ _ -> NoFlag++-- | Return the \"dist/\" prefix, or the default prefix. The prefix is taken+-- from (in order of highest to lowest preference) the override prefix, the+-- \"CABAL_BUILDDIR\" environment variable, or 'defaultDistPref' is used. Call+-- this function to resolve a @*DistPref@ flag whenever it is not known to be+-- set. (The @*DistPref@ flags are always set to a definite value before+-- invoking 'UserHooks'.)+findDistPrefOrDefault :: Setup.Flag FilePath -- ^ override \"dist\" prefix+ -> IO FilePath+findDistPrefOrDefault = findDistPref defaultDistPref++-- |Perform the \"@.\/setup configure@\" action.+-- Returns the @.setup-config@ file.+configure :: (GenericPackageDescription, HookedBuildInfo)+ -> ConfigFlags -> IO LocalBuildInfo+configure (pkg_descr0', pbi) cfg = do+ let pkg_descr0 =+ -- Ignore '--allow-newer' when we're given '--exact-configuration'.+ if fromFlagOrDefault False (configExactConfiguration cfg)+ then pkg_descr0'+ else relaxPackageDeps+ (fromMaybe AllowNewerNone $ configAllowNewer cfg)+ pkg_descr0'++ setupMessage verbosity "Configuring" (packageId pkg_descr0)++ checkDeprecatedFlags verbosity cfg+ checkExactConfiguration pkg_descr0 cfg++ -- Where to build the package+ let buildDir :: FilePath -- e.g. dist/build+ -- fromFlag OK due to Distribution.Simple calling+ -- findDistPrefOrDefault to fill it in+ buildDir = fromFlag (configDistPref cfg) </> "build"+ createDirectoryIfMissingVerbose (lessVerbose verbosity) True buildDir++ -- What package database(s) to use+ let packageDbs+ = interpretPackageDbFlags+ (fromFlag (configUserInstall cfg))+ (configPackageDBs cfg)++ -- comp: the compiler we're building with+ -- compPlatform: the platform we're building for+ -- programsConfig: location and args of all programs we're+ -- building with+ (comp, compPlatform, programsConfig)+ <- configCompilerEx+ (flagToMaybe (configHcFlavor cfg))+ (flagToMaybe (configHcPath cfg))+ (flagToMaybe (configHcPkg cfg))+ (mkProgramsConfig cfg (configPrograms cfg))+ (lessVerbose verbosity)++ -- The InstalledPackageIndex of all installed packages+ installedPackageSet <- getInstalledPackages (lessVerbose verbosity) comp+ packageDbs programsConfig++ -- The InstalledPackageIndex of all (possible) internal packages+ let internalPackageSet = getInternalPackages pkg_descr0++ -- allConstraints: The set of all 'Dependency's we have. Used ONLY+ -- to 'configureFinalizedPackage'.+ -- requiredDepsMap: A map from 'PackageName' to the specifically+ -- required 'InstalledPackageInfo', due to --dependency+ --+ -- NB: These constraints are to be applied to ALL components of+ -- a package. Thus, it's not an error if allConstraints contains+ -- more constraints than is necessary for a component (another+ -- component might need it.)+ --+ -- NB: The fact that we bundle all the constraints together means+ -- that is not possible to configure a test-suite to use one+ -- version of a dependency, and the executable to use another.+ (allConstraints, requiredDepsMap) <- either die return $+ combinedConstraints (configConstraints cfg)+ (configDependencies cfg)+ installedPackageSet++ -- pkg_descr: The resolved package description, that does not contain any+ -- conditionals, because we have have an assignment for+ -- every flag, either picking them ourselves using a+ -- simple naive algorithm, or having them be passed to+ -- us by 'configConfigurationsFlags')+ -- flags: The 'FlagAssignment' that the conditionals were+ -- resolved with.+ --+ -- NB: Why doesn't finalizing a package also tell us what the+ -- dependencies are (e.g. when we run the naive algorithm,+ -- we are checking if dependencies are satisfiable)? The+ -- primary reason is that we may NOT have done any solving:+ -- if the flags are all chosen for us, this step is a simple+ -- matter of flattening according to that assignment. It's+ -- cleaner to then configure the dependencies afterwards.+ (pkg_descr, flags)+ <- configureFinalizedPackage verbosity cfg+ allConstraints+ (dependencySatisfiable+ (fromFlagOrDefault False (configExactConfiguration cfg))+ installedPackageSet+ internalPackageSet+ requiredDepsMap)+ comp+ compPlatform+ pkg_descr0++ checkCompilerProblems comp pkg_descr+ checkPackageProblems verbosity pkg_descr0+ (updatePackageDescription pbi pkg_descr)++ -- The list of 'InstalledPackageInfo' recording the selected+ -- dependencies...+ -- internalPkgDeps: ...on internal packages (these are fake!)+ -- externalPkgDeps: ...on external packages+ --+ -- Invariant: For any package name, there is at most one package+ -- in externalPackageDeps which has that name.+ --+ -- NB: The dependency selection is global over ALL components+ -- in the package (similar to how allConstraints and+ -- requiredDepsMap are global over all components). In particular,+ -- if *any* component (post-flag resolution) has an unsatisfiable+ -- dependency, we will fail. This can sometimes be undesirable+ -- for users, see #1786 (benchmark conflicts with executable),+ (internalPkgDeps, externalPkgDeps)+ <- configureDependencies+ verbosity+ internalPackageSet+ installedPackageSet+ requiredDepsMap+ pkg_descr++ let installDeps = Map.elems -- deduplicate+ . Map.fromList+ . map (\v -> (Installed.installedUnitId v, v))+ $ externalPkgDeps++ packageDependsIndex <-+ case PackageIndex.dependencyClosure installedPackageSet+ (map Installed.installedUnitId installDeps) of+ Left packageDependsIndex -> return packageDependsIndex+ Right broken ->+ die $ "The following installed packages are broken because other"+ ++ " packages they depend on are missing. These broken "+ ++ "packages must be rebuilt before they can be used.\n"+ ++ unlines [ "package "+ ++ display (packageId pkg)+ ++ " is broken due to missing package "+ ++ intercalate ", " (map display deps)+ | (pkg, deps) <- broken ]++ let pseudoTopPkg = emptyInstalledPackageInfo {+ Installed.installedUnitId =+ mkLegacyUnitId (packageId pkg_descr),+ Installed.sourcePackageId = packageId pkg_descr,+ Installed.depends =+ map Installed.installedUnitId installDeps+ }+ case PackageIndex.dependencyInconsistencies+ . PackageIndex.insert pseudoTopPkg+ $ packageDependsIndex of+ [] -> return ()+ inconsistencies ->+ warn verbosity $+ "This package indirectly depends on multiple versions of the same "+ ++ "package. This is highly likely to cause a compile failure.\n"+ ++ unlines [ "package " ++ display pkg ++ " requires "+ ++ display (PackageIdentifier name ver)+ | (name, uses) <- inconsistencies+ , (pkg, ver) <- uses ]++ -- installation directories+ defaultDirs <- defaultInstallDirs (compilerFlavor comp)+ (fromFlag (configUserInstall cfg)) (hasLibs pkg_descr)+ let installDirs = combineInstallDirs fromFlagOrDefault+ defaultDirs (configInstallDirs cfg)++ -- check languages and extensions+ let langlist = nub $ catMaybes $ map defaultLanguage+ (allBuildInfo pkg_descr)+ let langs = unsupportedLanguages comp langlist+ when (not (null langs)) $+ die $ "The package " ++ display (packageId pkg_descr0)+ ++ " requires the following languages which are not "+ ++ "supported by " ++ display (compilerId comp) ++ ": "+ ++ intercalate ", " (map display langs)+ let extlist = nub $ concatMap allExtensions (allBuildInfo pkg_descr)+ let exts = unsupportedExtensions comp extlist+ when (not (null exts)) $+ die $ "The package " ++ display (packageId pkg_descr0)+ ++ " requires the following language extensions which are not "+ ++ "supported by " ++ display (compilerId comp) ++ ": "+ ++ intercalate ", " (map display exts)++ -- configured known/required programs & external build tools+ -- exclude build-tool deps on "internal" exes in the same package+ let requiredBuildTools =+ [ buildTool+ | let exeNames = map exeName (executables pkg_descr)+ , bi <- allBuildInfo pkg_descr+ , buildTool@(Dependency (PackageName toolName) reqVer)+ <- buildTools bi+ , let isInternal =+ toolName `elem` exeNames+ -- we assume all internal build-tools are+ -- versioned with the package:+ && packageVersion pkg_descr `withinRange` reqVer+ , not isInternal ]++ programsConfig' <-+ configureAllKnownPrograms (lessVerbose verbosity) programsConfig+ >>= configureRequiredPrograms verbosity requiredBuildTools++ (pkg_descr', programsConfig'') <-+ configurePkgconfigPackages verbosity pkg_descr programsConfig'++ -- internal component graph+ buildComponents <-+ case mkComponentsGraph pkg_descr internalPkgDeps of+ Left componentCycle -> reportComponentCycle componentCycle+ Right comps ->+ mkComponentsLocalBuildInfo cfg comp packageDependsIndex pkg_descr+ internalPkgDeps externalPkgDeps+ comps (configConfigurationsFlags cfg)++ split_objs <-+ if not (fromFlag $ configSplitObjs cfg)+ then return False+ else case compilerFlavor comp of+ GHC | compilerVersion comp >= Version [6,5] []+ -> return True+ GHCJS+ -> return True+ _ -> do warn verbosity+ ("this compiler does not support " +++ "--enable-split-objs; ignoring")+ return False++ let ghciLibByDefault =+ case compilerId comp of+ CompilerId GHC _ ->+ -- If ghc is non-dynamic, then ghci needs object files,+ -- so we build one by default.+ --+ -- Technically, archive files should be sufficient for ghci,+ -- but because of GHC bug #8942, it has never been safe to+ -- rely on them. By the time that bug was fixed, ghci had+ -- been changed to read shared libraries instead of archive+ -- files (see next code block).+ not (GHC.isDynamic comp)+ CompilerId GHCJS _ ->+ not (GHCJS.isDynamic comp)+ _ -> False++ let sharedLibsByDefault+ | fromFlag (configDynExe cfg) =+ -- build a shared library if dynamically-linked+ -- executables are requested+ True+ | otherwise = case compilerId comp of+ CompilerId GHC _ ->+ -- if ghc is dynamic, then ghci needs a shared+ -- library, so we build one by default.+ GHC.isDynamic comp+ CompilerId GHCJS _ ->+ GHCJS.isDynamic comp+ _ -> False+ withSharedLib_ =+ -- build shared libraries if required by GHC or by the+ -- executable linking mode, but allow the user to force+ -- building only static library archives with+ -- --disable-shared.+ fromFlagOrDefault sharedLibsByDefault $ configSharedLib cfg+ withDynExe_ = fromFlag $ configDynExe cfg+ when (withDynExe_ && not withSharedLib_) $ warn verbosity $+ "Executables will use dynamic linking, but a shared library "+ ++ "is not being built. Linking will fail if any executables "+ ++ "depend on the library."++ -- The --profiling flag sets the default for both libs and exes,+ -- but can be overidden by --library-profiling, or the old deprecated+ -- --executable-profiling flag.+ let profEnabledLibOnly = configProfLib cfg+ profEnabledBoth = fromFlagOrDefault False (configProf cfg)+ profEnabledLib = fromFlagOrDefault profEnabledBoth profEnabledLibOnly+ profEnabledExe = fromFlagOrDefault profEnabledBoth (configProfExe cfg)++ -- The --profiling-detail and --library-profiling-detail flags behave+ -- similarly+ profDetailLibOnly <- checkProfDetail (configProfLibDetail cfg)+ profDetailBoth <- liftM (fromFlagOrDefault ProfDetailDefault)+ (checkProfDetail (configProfDetail cfg))+ let profDetailLib = fromFlagOrDefault profDetailBoth profDetailLibOnly+ profDetailExe = profDetailBoth++ when (profEnabledExe && not profEnabledLib) $+ warn verbosity $+ "Executables will be built with profiling, but library "+ ++ "profiling is disabled. Linking will fail if any executables "+ ++ "depend on the library."++ let configCoverage_ =+ mappend (configCoverage cfg) (configLibCoverage cfg)++ cfg' = cfg { configCoverage = configCoverage_ }++ reloc <-+ if not (fromFlag $ configRelocatable cfg)+ then return False+ else return True++ let lbi = LocalBuildInfo {+ configFlags = cfg',+ flagAssignment = flags,+ extraConfigArgs = [], -- Currently configure does not+ -- take extra args, but if it+ -- did they would go here.+ installDirTemplates = installDirs,+ compiler = comp,+ hostPlatform = compPlatform,+ buildDir = buildDir,+ componentsConfigs = buildComponents,+ installedPkgs = packageDependsIndex,+ pkgDescrFile = Nothing,+ localPkgDescr = pkg_descr',+ withPrograms = programsConfig'',+ withVanillaLib = fromFlag $ configVanillaLib cfg,+ withProfLib = profEnabledLib,+ withSharedLib = withSharedLib_,+ withDynExe = withDynExe_,+ withProfExe = profEnabledExe,+ withProfLibDetail = profDetailLib,+ withProfExeDetail = profDetailExe,+ withOptimization = fromFlag $ configOptimization cfg,+ withDebugInfo = fromFlag $ configDebugInfo cfg,+ withGHCiLib = fromFlagOrDefault ghciLibByDefault $+ configGHCiLib cfg,+ splitObjs = split_objs,+ stripExes = fromFlag $ configStripExes cfg,+ stripLibs = fromFlag $ configStripLibs cfg,+ withPackageDB = packageDbs,+ progPrefix = fromFlag $ configProgPrefix cfg,+ progSuffix = fromFlag $ configProgSuffix cfg,+ relocatable = reloc+ }++ when reloc (checkRelocatable verbosity pkg_descr lbi)++ let dirs = absoluteInstallDirs pkg_descr lbi NoCopyDest+ relative = prefixRelativeInstallDirs (packageId pkg_descr) lbi++ unless (isAbsolute (prefix dirs)) $ die $+ "expected an absolute directory name for --prefix: " ++ prefix dirs++ info verbosity $ "Using " ++ display currentCabalId+ ++ " compiled by " ++ display currentCompilerId+ info verbosity $ "Using compiler: " ++ showCompilerId comp+ info verbosity $ "Using install prefix: " ++ prefix dirs++ let dirinfo name dir isPrefixRelative =+ info verbosity $ name ++ " installed in: " ++ dir ++ relNote+ where relNote = case buildOS of+ Windows | not (hasLibs pkg_descr)+ && isNothing isPrefixRelative+ -> " (fixed location)"+ _ -> ""++ dirinfo "Binaries" (bindir dirs) (bindir relative)+ dirinfo "Libraries" (libdir dirs) (libdir relative)+ dirinfo "Private binaries" (libexecdir dirs) (libexecdir relative)+ dirinfo "Data files" (datadir dirs) (datadir relative)+ dirinfo "Documentation" (docdir dirs) (docdir relative)+ dirinfo "Configuration files" (sysconfdir dirs) (sysconfdir relative)++ sequence_ [ reportProgram verbosity prog configuredProg+ | (prog, configuredProg) <- knownPrograms programsConfig'' ]++ return lbi++ where+ verbosity = fromFlag (configVerbosity cfg)++ checkProfDetail (Flag (ProfDetailOther other)) = do+ warn verbosity $+ "Unknown profiling detail level '" ++ other+ ++ "', using default.\n"+ ++ "The profiling detail levels are: " ++ intercalate ", "+ [ name | (name, _, _) <- knownProfDetailLevels ]+ return (Flag ProfDetailDefault)+ checkProfDetail other = return other++mkProgramsConfig :: ConfigFlags -> ProgramConfiguration -> ProgramConfiguration+mkProgramsConfig cfg initialProgramsConfig = programsConfig+ where+ programsConfig = userSpecifyArgss (configProgramArgs cfg)+ . userSpecifyPaths (configProgramPaths cfg)+ . setProgramSearchPath searchpath+ $ initialProgramsConfig+ searchpath = getProgramSearchPath (initialProgramsConfig)+ ++ map ProgramSearchPathDir+ (fromNubList $ configProgramPathExtra cfg)++-- -----------------------------------------------------------------------------+-- Helper functions for configure++-- | Check if the user used any deprecated flags.+checkDeprecatedFlags :: Verbosity -> ConfigFlags -> IO ()+checkDeprecatedFlags verbosity cfg = do+ unless (configProfExe cfg == NoFlag) $ do+ let enable | fromFlag (configProfExe cfg) = "enable"+ | otherwise = "disable"+ warn verbosity+ ("The flag --" ++ enable ++ "-executable-profiling is deprecated. "+ ++ "Please use --" ++ enable ++ "-profiling instead.")++ unless (configLibCoverage cfg == NoFlag) $ do+ let enable | fromFlag (configLibCoverage cfg) = "enable"+ | otherwise = "disable"+ warn verbosity+ ("The flag --" ++ enable ++ "-library-coverage is deprecated. "+ ++ "Please use --" ++ enable ++ "-coverage instead.")++-- | Sanity check: if '--exact-configuration' was given, ensure that the+-- complete flag assignment was specified on the command line.+checkExactConfiguration :: GenericPackageDescription -> ConfigFlags -> IO ()+checkExactConfiguration pkg_descr0 cfg = do+ when (fromFlagOrDefault False (configExactConfiguration cfg)) $ do+ let cmdlineFlags = map fst (configConfigurationsFlags cfg)+ allFlags = map flagName . genPackageFlags $ pkg_descr0+ diffFlags = allFlags \\ cmdlineFlags+ when (not . null $ diffFlags) $+ die $ "'--exact-configuration' was given, "+ ++ "but the following flags were not specified: "+ ++ intercalate ", " (map show diffFlags)++-- | Create a PackageIndex that makes *any libraries that might be*+-- defined internally to this package look like installed packages, in+-- case an executable should refer to any of them as dependencies.+--+-- It must be *any libraries that might be* defined rather than the+-- actual definitions, because these depend on conditionals in the .cabal+-- file, and we haven't resolved them yet. finalizePackageDescription+-- does the resolution of conditionals, and it takes internalPackageSet+-- as part of its input.+--+-- Currently a package can define no more than one library (which has+-- the same name as the package) but we could extend this later.+-- If we later allowed private internal libraries, then here we would+-- need to pre-scan the conditional data to make a list of all private+-- libraries that could possibly be defined by the .cabal file.+getInternalPackages :: GenericPackageDescription+ -> InstalledPackageIndex+getInternalPackages pkg_descr0 =+ let pid :: PackageIdentifier -- e.g. foo-0.1+ pid = packageId pkg_descr0+ internalPackage = emptyInstalledPackageInfo {+ --TODO: should use a per-compiler method to map the source+ -- package ID into an installed package id we can use+ -- for the internal package set. The use of+ -- mkLegacyUnitId here is a hack.+ Installed.installedUnitId = mkLegacyUnitId pid,+ Installed.sourcePackageId = pid+ }+ in PackageIndex.fromList [internalPackage]+++-- | Returns true if a dependency is satisfiable. This is to be passed+-- to finalizePackageDescription.+dependencySatisfiable+ :: Bool+ -> InstalledPackageIndex -- ^ installed set+ -> InstalledPackageIndex -- ^ internal set+ -> Map PackageName InstalledPackageInfo -- ^ required dependencies+ -> (Dependency -> Bool)+dependencySatisfiable+ exact_config installedPackageSet internalPackageSet requiredDepsMap+ d@(Dependency depName _)+ | exact_config =+ -- When we're given '--exact-configuration', we assume that all+ -- dependencies and flags are exactly specified on the command+ -- line. Thus we only consult the 'requiredDepsMap'. Note that+ -- we're not doing the version range check, so if there's some+ -- dependency that wasn't specified on the command line,+ -- 'finalizePackageDescription' will fail.+ --+ -- TODO: mention '--exact-configuration' in the error message+ -- when this fails?+ --+ -- (However, note that internal deps don't have to be+ -- specified!)+ (depName `Map.member` requiredDepsMap) || isInternalDep++ | otherwise =+ -- Normal operation: just look up dependency in the combined+ -- package index.+ not . null . PackageIndex.lookupDependency pkgs $ d+ where+ pkgs = PackageIndex.merge internalPackageSet installedPackageSet+ isInternalDep = not . null+ $ PackageIndex.lookupDependency internalPackageSet d++-- | Relax the dependencies of this package if needed.+relaxPackageDeps :: AllowNewer -> GenericPackageDescription+ -> GenericPackageDescription+relaxPackageDeps AllowNewerNone gpd = gpd+relaxPackageDeps AllowNewerAll gpd = transformAllBuildDepends relaxAll gpd+ where+ relaxAll = \(Dependency pkgName verRange) ->+ Dependency pkgName (removeUpperBound verRange)+relaxPackageDeps (AllowNewerSome allowNewerDeps') gpd =+ transformAllBuildDepends relaxSome gpd+ where+ thisPkgName = packageName gpd+ allowNewerDeps = mapMaybe f allowNewerDeps'++ f (Setup.AllowNewerDep p) = Just p+ f (Setup.AllowNewerDepScoped scope p) | scope == thisPkgName = Just p+ | otherwise = Nothing++ relaxSome = \d@(Dependency depName verRange) ->+ if depName `elem` allowNewerDeps+ then Dependency depName (removeUpperBound verRange)+ else d++-- | Finalize a generic package description. The workhorse is+-- 'finalizePackageDescription' but there's a bit of other nattering+-- about necessary.+--+-- TODO: what exactly is the business with @flaggedTests@ and+-- @flaggedBenchmarks@?+configureFinalizedPackage+ :: Verbosity+ -> ConfigFlags+ -> [Dependency]+ -> (Dependency -> Bool) -- ^ tests if a dependency is satisfiable.+ -- Might say it's satisfiable even when not.+ -> Compiler+ -> Platform+ -> GenericPackageDescription+ -> IO (PackageDescription, FlagAssignment)+configureFinalizedPackage verbosity cfg+ allConstraints satisfies comp compPlatform pkg_descr0 = do+ let enableTest t = t { testEnabled = fromFlag (configTests cfg) }+ flaggedTests = map (\(n, t) -> (n, mapTreeData enableTest t))+ (condTestSuites pkg_descr0)+ enableBenchmark bm = bm { benchmarkEnabled =+ fromFlag (configBenchmarks cfg) }+ flaggedBenchmarks = map (\(n, bm) ->+ (n, mapTreeData enableBenchmark bm))+ (condBenchmarks pkg_descr0)+ pkg_descr0'' = pkg_descr0 { condTestSuites = flaggedTests+ , condBenchmarks = flaggedBenchmarks }++ (pkg_descr0', flags) <-+ case finalizePackageDescription+ (configConfigurationsFlags cfg)+ satisfies+ compPlatform+ (compilerInfo comp)+ allConstraints+ pkg_descr0''+ of Right r -> return r+ Left missing ->+ die $ "Encountered missing dependencies:\n"+ ++ (render . nest 4 . sep . punctuate comma+ . map (disp . simplifyDependency)+ $ missing)++ -- add extra include/lib dirs as specified in cfg+ -- we do it here so that those get checked too+ let pkg_descr = addExtraIncludeLibDirs pkg_descr0'++ when (not (null flags)) $+ info verbosity $ "Flags chosen: "+ ++ intercalate ", " [ name ++ "=" ++ display value+ | (FlagName name, value) <- flags ]++ return (pkg_descr, flags)+ where+ addExtraIncludeLibDirs pkg_descr =+ let extraBi = mempty { extraLibDirs = configExtraLibDirs cfg+ , extraFrameworkDirs = configExtraFrameworkDirs cfg+ , PD.includeDirs = configExtraIncludeDirs cfg}+ modifyLib l = l{ libBuildInfo = libBuildInfo l+ `mappend` extraBi }+ modifyExecutable e = e{ buildInfo = buildInfo e+ `mappend` extraBi}+ in pkg_descr{ library = modifyLib `fmap` library pkg_descr+ , executables = modifyExecutable `map`+ executables pkg_descr}++-- | Check for use of Cabal features which require compiler support+checkCompilerProblems :: Compiler -> PackageDescription -> IO ()+checkCompilerProblems comp pkg_descr = do+ unless (renamingPackageFlagsSupported comp ||+ and [ True+ | bi <- allBuildInfo pkg_descr+ , _ <- Map.elems (targetBuildRenaming bi)]) $+ die $ "Your compiler does not support thinning and renaming on "+ ++ "package flags. To use this feature you probably must use "+ ++ "GHC 7.9 or later."++ when (maybe False (not.null.PD.reexportedModules) (PD.library pkg_descr)+ && not (reexportedModulesSupported comp)) $ do+ die $ "Your compiler does not support module re-exports. To use "+ ++ "this feature you probably must use GHC 7.9 or later."++-- | Select dependencies for the package.+configureDependencies+ :: Verbosity+ -> InstalledPackageIndex -- ^ internal packages+ -> InstalledPackageIndex -- ^ installed packages+ -> Map PackageName InstalledPackageInfo -- ^ required deps+ -> PackageDescription+ -> IO ([PackageId], [InstalledPackageInfo])+configureDependencies verbosity+ internalPackageSet installedPackageSet requiredDepsMap pkg_descr = do+ let selectDependencies :: [Dependency] ->+ ([FailedDependency], [ResolvedDependency])+ selectDependencies =+ partitionEithers+ . map (selectDependency internalPackageSet installedPackageSet+ requiredDepsMap)++ (failedDeps, allPkgDeps) =+ selectDependencies (buildDepends pkg_descr)++ internalPkgDeps = [ pkgid+ | InternalDependency _ pkgid <- allPkgDeps ]+ externalPkgDeps = [ pkg+ | ExternalDependency _ pkg <- allPkgDeps ]++ when (not (null internalPkgDeps)+ && not (newPackageDepsBehaviour pkg_descr)) $+ die $ "The field 'build-depends: "+ ++ intercalate ", " (map (display . packageName) internalPkgDeps)+ ++ "' refers to a library which is defined within the same "+ ++ "package. To use this feature the package must specify at "+ ++ "least 'cabal-version: >= 1.8'."++ reportFailedDependencies failedDeps+ reportSelectedDependencies verbosity allPkgDeps++ return (internalPkgDeps, externalPkgDeps)++-- -----------------------------------------------------------------------------+-- Configuring package dependencies++reportProgram :: Verbosity -> Program -> Maybe ConfiguredProgram -> IO ()+reportProgram verbosity prog Nothing+ = info verbosity $ "No " ++ programName prog ++ " found"+reportProgram verbosity prog (Just configuredProg)+ = info verbosity $ "Using " ++ programName prog ++ version ++ location+ where location = case programLocation configuredProg of+ FoundOnSystem p -> " found on system at: " ++ p+ UserSpecified p -> " given by user at: " ++ p+ version = case programVersion configuredProg of+ Nothing -> ""+ Just v -> " version " ++ display v++hackageUrl :: String+hackageUrl = "http://hackage.haskell.org/package/"++data ResolvedDependency = ExternalDependency Dependency InstalledPackageInfo+ | InternalDependency Dependency PackageId -- should be a+ -- lib name++data FailedDependency = DependencyNotExists PackageName+ | DependencyNoVersion Dependency++-- | Test for a package dependency and record the version we have installed.+selectDependency :: InstalledPackageIndex -- ^ Internally defined packages+ -> InstalledPackageIndex -- ^ Installed packages+ -> Map PackageName InstalledPackageInfo+ -- ^ Packages for which we have been given specific deps to+ -- use+ -> Dependency+ -> Either FailedDependency ResolvedDependency+selectDependency internalIndex installedIndex requiredDepsMap+ dep@(Dependency pkgname vr) =+ -- If the dependency specification matches anything in the internal package+ -- index, then we prefer that match to anything in the second.+ -- For example:+ --+ -- Name: MyLibrary+ -- Version: 0.1+ -- Library+ -- ..+ -- Executable my-exec+ -- build-depends: MyLibrary+ --+ -- We want "build-depends: MyLibrary" always to match the internal library+ -- even if there is a newer installed library "MyLibrary-0.2".+ -- However, "build-depends: MyLibrary >= 0.2" should match the installed one.+ case PackageIndex.lookupPackageName internalIndex pkgname of+ [(_,[pkg])] | packageVersion pkg `withinRange` vr+ -> Right $ InternalDependency dep (packageId pkg)++ _ -> case Map.lookup pkgname requiredDepsMap of+ -- If we know the exact pkg to use, then use it.+ Just pkginstance -> Right (ExternalDependency dep pkginstance)+ -- Otherwise we just pick an arbitrary instance of the latest version.+ Nothing -> case PackageIndex.lookupDependency installedIndex dep of+ [] -> Left $ DependencyNotExists pkgname+ pkgs -> Right $ ExternalDependency dep $+ case last pkgs of+ (_ver, pkginstances) -> head pkginstances++reportSelectedDependencies :: Verbosity+ -> [ResolvedDependency] -> IO ()+reportSelectedDependencies verbosity deps =+ info verbosity $ unlines+ [ "Dependency " ++ display (simplifyDependency dep)+ ++ ": using " ++ display pkgid+ | resolved <- deps+ , let (dep, pkgid) = case resolved of+ ExternalDependency dep' pkg' -> (dep', packageId pkg')+ InternalDependency dep' pkgid' -> (dep', pkgid') ]++reportFailedDependencies :: [FailedDependency] -> IO ()+reportFailedDependencies [] = return ()+reportFailedDependencies failed =+ die (intercalate "\n\n" (map reportFailedDependency failed))++ where+ reportFailedDependency (DependencyNotExists pkgname) =+ "there is no version of " ++ display pkgname ++ " installed.\n"+ ++ "Perhaps you need to download and install it from\n"+ ++ hackageUrl ++ display pkgname ++ "?"++ reportFailedDependency (DependencyNoVersion dep) =+ "cannot satisfy dependency " ++ display (simplifyDependency dep) ++ "\n"++-- | List all installed packages in the given package databases.+getInstalledPackages :: Verbosity -> Compiler+ -> PackageDBStack -- ^ The stack of package databases.+ -> ProgramConfiguration+ -> IO InstalledPackageIndex+getInstalledPackages verbosity comp packageDBs progconf = do+ when (null packageDBs) $+ die $ "No package databases have been specified. If you use "+ ++ "--package-db=clear, you must follow it with --package-db= "+ ++ "with 'global', 'user' or a specific file."++ info verbosity "Reading installed packages..."+ case compilerFlavor comp of+ GHC -> GHC.getInstalledPackages verbosity comp packageDBs progconf+ GHCJS -> GHCJS.getInstalledPackages verbosity packageDBs progconf+ JHC -> JHC.getInstalledPackages verbosity packageDBs progconf+ LHC -> LHC.getInstalledPackages verbosity packageDBs progconf+ UHC -> UHC.getInstalledPackages verbosity comp packageDBs progconf+ HaskellSuite {} ->+ HaskellSuite.getInstalledPackages verbosity packageDBs progconf+ flv -> die $ "don't know how to find the installed packages for "+ ++ display flv++-- | Like 'getInstalledPackages', but for a single package DB.+--+-- NB: Why isn't this always a fall through to 'getInstalledPackages'?+-- That is because 'getInstalledPackages' performs some sanity checks+-- on the package database stack in question. However, when sandboxes+-- are involved these sanity checks are not desirable.+getPackageDBContents :: Verbosity -> Compiler+ -> PackageDB -> ProgramConfiguration+ -> IO InstalledPackageIndex+getPackageDBContents verbosity comp packageDB progconf = do+ info verbosity "Reading installed packages..."+ case compilerFlavor comp of+ GHC -> GHC.getPackageDBContents verbosity packageDB progconf+ GHCJS -> GHCJS.getPackageDBContents verbosity packageDB progconf+ -- For other compilers, try to fall back on 'getInstalledPackages'.+ _ -> getInstalledPackages verbosity comp [packageDB] progconf+++-- | A set of files (or directories) that can be monitored to detect when+-- there might have been a change in the installed packages.+--+getInstalledPackagesMonitorFiles :: Verbosity -> Compiler+ -> PackageDBStack+ -> ProgramConfiguration -> Platform+ -> IO [FilePath]+getInstalledPackagesMonitorFiles verbosity comp packageDBs progconf platform =+ case compilerFlavor comp of+ GHC -> GHC.getInstalledPackagesMonitorFiles+ verbosity platform progconf packageDBs+ other -> do+ warn verbosity $ "don't know how to find change monitoring files for "+ ++ "the installed package databases for " ++ display other+ return []++-- | The user interface specifies the package dbs to use with a combination of+-- @--global@, @--user@ and @--package-db=global|user|clear|$file@.+-- This function combines the global/user flag and interprets the package-db+-- flag into a single package db stack.+--+interpretPackageDbFlags :: Bool -> [Maybe PackageDB] -> PackageDBStack+interpretPackageDbFlags userInstall specificDBs =+ extra initialStack specificDBs+ where+ initialStack | userInstall = [GlobalPackageDB, UserPackageDB]+ | otherwise = [GlobalPackageDB]++ extra dbs' [] = dbs'+ extra _ (Nothing:dbs) = extra [] dbs+ extra dbs' (Just db:dbs) = extra (dbs' ++ [db]) dbs++newPackageDepsBehaviourMinVersion :: Version+newPackageDepsBehaviourMinVersion = Version [1,7,1] []++-- In older cabal versions, there was only one set of package dependencies for+-- the whole package. In this version, we can have separate dependencies per+-- target, but we only enable this behaviour if the minimum cabal version+-- specified is >= a certain minimum. Otherwise, for compatibility we use the+-- old behaviour.+newPackageDepsBehaviour :: PackageDescription -> Bool+newPackageDepsBehaviour pkg =+ specVersion pkg >= newPackageDepsBehaviourMinVersion++-- We are given both --constraint="foo < 2.0" style constraints and also+-- specific packages to pick via --dependency="foo=foo-2.0-177d5cdf20962d0581".+--+-- When finalising the package we have to take into account the specific+-- installed deps we've been given, and the finalise function expects+-- constraints, so we have to translate these deps into version constraints.+--+-- But after finalising we then have to make sure we pick the right specific+-- deps in the end. So we still need to remember which installed packages to+-- pick.+combinedConstraints :: [Dependency] ->+ [(PackageName, UnitId)] ->+ InstalledPackageIndex ->+ Either String ([Dependency],+ Map PackageName InstalledPackageInfo)+combinedConstraints constraints dependencies installedPackages = do++ when (not (null badUnitIds)) $+ Left $ render $ text "The following package dependencies were requested"+ $+$ nest 4 (dispDependencies badUnitIds)+ $+$ text "however the given installed package instance does not exist."++ when (not (null badNames)) $+ Left $ render $ text "The following package dependencies were requested"+ $+$ nest 4 (dispDependencies badNames)+ $+$ text ("however the installed package's name does not match "+ ++ "the name given.")++ --TODO: we don't check that all dependencies are used!++ return (allConstraints, idConstraintMap)++ where+ allConstraints :: [Dependency]+ allConstraints = constraints+ ++ [ thisPackageVersion (packageId pkg)+ | (_, _, Just pkg) <- dependenciesPkgInfo ]++ idConstraintMap :: Map PackageName InstalledPackageInfo+ idConstraintMap = Map.fromList+ [ (packageName pkg, pkg)+ | (_, _, Just pkg) <- dependenciesPkgInfo ]++ -- The dependencies along with the installed package info, if it exists+ dependenciesPkgInfo :: [(PackageName, UnitId,+ Maybe InstalledPackageInfo)]+ dependenciesPkgInfo =+ [ (pkgname, ipkgid, mpkg)+ | (pkgname, ipkgid) <- dependencies+ , let mpkg = PackageIndex.lookupUnitId+ installedPackages ipkgid+ ]++ -- If we looked up a package specified by an installed package id+ -- (i.e. someone has written a hash) and didn't find it then it's+ -- an error.+ badUnitIds =+ [ (pkgname, ipkgid)+ | (pkgname, ipkgid, Nothing) <- dependenciesPkgInfo ]++ -- If someone has written e.g.+ -- --dependency="foo=MyOtherLib-1.0-07...5bf30" then they have+ -- probably made a mistake.+ badNames =+ [ (requestedPkgName, ipkgid)+ | (requestedPkgName, ipkgid, Just pkg) <- dependenciesPkgInfo+ , let foundPkgName = packageName pkg+ , requestedPkgName /= foundPkgName ]++ dispDependencies deps =+ hsep [ text "--dependency="+ <> quotes (disp pkgname <> char '=' <> disp ipkgid)+ | (pkgname, ipkgid) <- deps ]++-- -----------------------------------------------------------------------------+-- Configuring program dependencies++configureRequiredPrograms :: Verbosity -> [Dependency] -> ProgramConfiguration+ -> IO ProgramConfiguration+configureRequiredPrograms verbosity deps conf =+ foldM (configureRequiredProgram verbosity) conf deps++configureRequiredProgram :: Verbosity -> ProgramConfiguration -> Dependency+ -> IO ProgramConfiguration+configureRequiredProgram verbosity conf+ (Dependency (PackageName progName) verRange) =+ case lookupKnownProgram progName conf of+ Nothing -> die ("Unknown build tool " ++ progName)+ Just prog+ -- requireProgramVersion always requires the program have a version+ -- but if the user says "build-depends: foo" ie no version constraint+ -- then we should not fail if we cannot discover the program version.+ | verRange == anyVersion -> do+ (_, conf') <- requireProgram verbosity prog conf+ return conf'+ | otherwise -> do+ (_, _, conf') <- requireProgramVersion verbosity prog verRange conf+ return conf'++-- -----------------------------------------------------------------------------+-- Configuring pkg-config package dependencies++configurePkgconfigPackages :: Verbosity -> PackageDescription+ -> ProgramConfiguration+ -> IO (PackageDescription, ProgramConfiguration)+configurePkgconfigPackages verbosity pkg_descr conf+ | null allpkgs = return (pkg_descr, conf)+ | otherwise = do+ (_, _, conf') <- requireProgramVersion+ (lessVerbose verbosity) pkgConfigProgram+ (orLaterVersion $ Version [0,9,0] []) conf+ mapM_ requirePkg allpkgs+ lib' <- mapM addPkgConfigBILib (library pkg_descr)+ exes' <- mapM addPkgConfigBIExe (executables pkg_descr)+ tests' <- mapM addPkgConfigBITest (testSuites pkg_descr)+ benches' <- mapM addPkgConfigBIBench (benchmarks pkg_descr)+ let pkg_descr' = pkg_descr { library = lib', executables = exes',+ testSuites = tests', benchmarks = benches' }+ return (pkg_descr', conf')++ where+ allpkgs = concatMap pkgconfigDepends (allBuildInfo pkg_descr)+ pkgconfig = rawSystemProgramStdoutConf (lessVerbose verbosity)+ pkgConfigProgram conf++ requirePkg dep@(Dependency (PackageName pkg) range) = do+ version <- pkgconfig ["--modversion", pkg]+ `catchIO` (\_ -> die notFound)+ `catchExit` (\_ -> die notFound)+ case simpleParse version of+ Nothing -> die "parsing output of pkg-config --modversion failed"+ Just v | not (withinRange v range) -> die (badVersion v)+ | otherwise -> info verbosity (depSatisfied v)+ where+ notFound = "The pkg-config package '" ++ pkg ++ "'"+ ++ versionRequirement+ ++ " is required but it could not be found."+ badVersion v = "The pkg-config package '" ++ pkg ++ "'"+ ++ versionRequirement+ ++ " is required but the version installed on the"+ ++ " system is version " ++ display v+ depSatisfied v = "Dependency " ++ display dep+ ++ ": using version " ++ display v++ versionRequirement+ | isAnyVersion range = ""+ | otherwise = " version " ++ display range++ -- Adds pkgconfig dependencies to the build info for a component+ addPkgConfigBI compBI setCompBI comp = do+ bi <- pkgconfigBuildInfo (pkgconfigDepends (compBI comp))+ return $ setCompBI comp (compBI comp `mappend` bi)++ -- Adds pkgconfig dependencies to the build info for a library+ addPkgConfigBILib = addPkgConfigBI libBuildInfo $+ \lib bi -> lib { libBuildInfo = bi }++ -- Adds pkgconfig dependencies to the build info for an executable+ addPkgConfigBIExe = addPkgConfigBI buildInfo $+ \exe bi -> exe { buildInfo = bi }++ -- Adds pkgconfig dependencies to the build info for a test suite+ addPkgConfigBITest = addPkgConfigBI testBuildInfo $+ \test bi -> test { testBuildInfo = bi }++ -- Adds pkgconfig dependencies to the build info for a benchmark+ addPkgConfigBIBench = addPkgConfigBI benchmarkBuildInfo $+ \bench bi -> bench { benchmarkBuildInfo = bi }++ pkgconfigBuildInfo :: [Dependency] -> IO BuildInfo+ pkgconfigBuildInfo [] = return Mon.mempty+ pkgconfigBuildInfo pkgdeps = do+ let pkgs = nub [ display pkg | Dependency pkg _ <- pkgdeps ]+ ccflags <- pkgconfig ("--cflags" : pkgs)+ ldflags <- pkgconfig ("--libs" : pkgs)+ return (ccLdOptionsBuildInfo (words ccflags) (words ldflags))++-- | Makes a 'BuildInfo' from C compiler and linker flags.+--+-- This can be used with the output from configuration programs like pkg-config+-- and similar package-specific programs like mysql-config, freealut-config etc.+-- For example:+--+-- > ccflags <- rawSystemProgramStdoutConf verbosity prog conf ["--cflags"]+-- > ldflags <- rawSystemProgramStdoutConf verbosity prog conf ["--libs"]+-- > return (ccldOptionsBuildInfo (words ccflags) (words ldflags))+--+ccLdOptionsBuildInfo :: [String] -> [String] -> BuildInfo+ccLdOptionsBuildInfo cflags ldflags =+ let (includeDirs', cflags') = partition ("-I" `isPrefixOf`) cflags+ (extraLibs', ldflags') = partition ("-l" `isPrefixOf`) ldflags+ (extraLibDirs', ldflags'') = partition ("-L" `isPrefixOf`) ldflags'+ in mempty {+ PD.includeDirs = map (drop 2) includeDirs',+ PD.extraLibs = map (drop 2) extraLibs',+ PD.extraLibDirs = map (drop 2) extraLibDirs',+ PD.ccOptions = cflags',+ PD.ldOptions = ldflags''+ }++-- -----------------------------------------------------------------------------+-- Determining the compiler details++configCompilerAuxEx :: ConfigFlags+ -> IO (Compiler, Platform, ProgramConfiguration)+configCompilerAuxEx cfg = configCompilerEx (flagToMaybe $ configHcFlavor cfg)+ (flagToMaybe $ configHcPath cfg)+ (flagToMaybe $ configHcPkg cfg)+ programsConfig+ (fromFlag (configVerbosity cfg))+ where+ programsConfig = mkProgramsConfig cfg defaultProgramConfiguration++configCompilerEx :: Maybe CompilerFlavor -> Maybe FilePath -> Maybe FilePath+ -> ProgramConfiguration -> Verbosity+ -> IO (Compiler, Platform, ProgramConfiguration)+configCompilerEx Nothing _ _ _ _ = die "Unknown compiler"+configCompilerEx (Just hcFlavor) hcPath hcPkg conf verbosity = do+ (comp, maybePlatform, programsConfig) <- case hcFlavor of+ GHC -> GHC.configure verbosity hcPath hcPkg conf+ GHCJS -> GHCJS.configure verbosity hcPath hcPkg conf+ JHC -> JHC.configure verbosity hcPath hcPkg conf+ LHC -> do (_, _, ghcConf) <- GHC.configure verbosity Nothing hcPkg conf+ LHC.configure verbosity hcPath Nothing ghcConf+ UHC -> UHC.configure verbosity hcPath hcPkg conf+ HaskellSuite {} -> HaskellSuite.configure verbosity hcPath hcPkg conf+ _ -> die "Unknown compiler"+ return (comp, fromMaybe buildPlatform maybePlatform, programsConfig)++-- Ideally we would like to not have separate configCompiler* and+-- configCompiler*Ex sets of functions, but there are many custom setup scripts+-- in the wild that are using them, so the versions with old types are kept for+-- backwards compatibility. Platform was added to the return triple in 1.18.++{-# DEPRECATED configCompiler+ "'configCompiler' is deprecated. Use 'configCompilerEx' instead." #-}+configCompiler :: Maybe CompilerFlavor -> Maybe FilePath -> Maybe FilePath+ -> ProgramConfiguration -> Verbosity+ -> IO (Compiler, ProgramConfiguration)+configCompiler mFlavor hcPath hcPkg conf verbosity =+ fmap (\(a,_,b) -> (a,b)) $ configCompilerEx mFlavor hcPath hcPkg conf verbosity++{-# DEPRECATED configCompilerAux+ "configCompilerAux is deprecated. Use 'configCompilerAuxEx' instead." #-}+configCompilerAux :: ConfigFlags+ -> IO (Compiler, ProgramConfiguration)+configCompilerAux = fmap (\(a,_,b) -> (a,b)) . configCompilerAuxEx++-- -----------------------------------------------------------------------------+-- Making the internal component graph+++mkComponentsGraph :: PackageDescription+ -> [PackageId]+ -> Either [ComponentName]+ [(Component, [ComponentName])]+mkComponentsGraph pkg_descr internalPkgDeps =+ let graph = [ (c, componentName c, componentDeps c)+ | c <- pkgEnabledComponents pkg_descr ]+ in case checkComponentsCyclic graph of+ Just ccycle -> Left [ cname | (_,cname,_) <- ccycle ]+ Nothing -> Right [ (c, cdeps) | (c, _, cdeps) <- graph ]+ where+ -- The dependencies for the given component+ componentDeps component =+ [ CExeName toolname | Dependency (PackageName toolname) _+ <- buildTools bi+ , toolname `elem` map exeName+ (executables pkg_descr) ]++ ++ [ CLibName | Dependency pkgname _ <- targetBuildDepends bi+ , pkgname `elem` map packageName internalPkgDeps ]+ where+ bi = componentBuildInfo component++reportComponentCycle :: [ComponentName] -> IO a+reportComponentCycle cnames =+ die $ "Components in the package depend on each other in a cyclic way:\n "+ ++ intercalate " depends on "+ [ "'" ++ showComponentName cname ++ "'"+ | cname <- cnames ++ [head cnames] ]++-- | This method computes a default, "good enough" 'ComponentId'+-- for a package. The intent is that cabal-install (or the user) will+-- specify a more detailed IPID via the @--ipid@ flag if necessary.+computeComponentId :: PackageIdentifier+ -> ComponentName+ -- TODO: careful here!+ -> [ComponentId] -- IPIDs of the component dependencies+ -> FlagAssignment+ -> ComponentId+computeComponentId pid cname dep_ipids flagAssignment = do+ -- show is found to be faster than intercalate and then replacement of+ -- special character used in intercalating. We cannot simply hash by+ -- doubly concating list, as it just flatten out the nested list, so+ -- different sources can produce same hash+ let hash = hashToBase62 $+ -- For safety, include the package + version here+ -- for GHC 7.10, where just the hash is used as+ -- the package key+ (display pid)+ ++ (show $ dep_ipids)+ ++ show flagAssignment+ ComponentId $+ display pid+ ++ "-" ++ hash+ ++ (case cname of+ CLibName -> ""+ -- TODO: these could result in non-parseable IPIDs+ -- since the component name format is very flexible+ CExeName s -> "-" ++ s ++ ".exe"+ CTestName s -> "-" ++ s ++ ".test"+ CBenchName s -> "-" ++ s ++ ".bench")++hashToBase62 :: String -> String+hashToBase62 s = showFingerprint $ fingerprintString s+ where+ showIntAtBase62 x = showIntAtBase 62 representBase62 x ""+ representBase62 x+ | x < 10 = chr (48 + x)+ | x < 36 = chr (65 + x - 10)+ | x < 62 = chr (97 + x - 36)+ | otherwise = '@'+ showFingerprint (Fingerprint a b) = showIntAtBase62 a ++ showIntAtBase62 b++-- | In GHC 8.0, the string we pass to GHC to use for symbol+-- names for a package can be an arbitrary, IPID-compatible string.+-- However, prior to GHC 8.0 there are some restrictions on what+-- format this string can be (due to how ghc-pkg parsed the key):+--+-- 1. In GHC 7.10, the string had either be of the form+-- foo_ABCD, where foo is a non-semantic alphanumeric/hyphenated+-- prefix and ABCD is two base-64 encoded 64-bit integers,+-- or a GHC 7.8 style identifier.+--+-- 2. In GHC 7.8, the string had to be a valid package identifier+-- like foo-0.1.+--+-- So, the problem is that Cabal, in general, has a general IPID,+-- but needs to figure out a package key / package ID that the+-- old ghc-pkg will actually accept. But there's an EVERY WORSE+-- problem: if ghc-pkg decides to parse an identifier foo-0.1-xxx+-- as if it were a package identifier, which means it will SILENTLY+-- DROP the "xxx" (because it's a tag, and Cabal does not allow tags.)+-- So we must CONNIVE to ensure that we don't pick something that+-- looks like this.+--+-- So this function attempts to define a mapping into the old formats.+--+-- The mapping for GHC 7.8 and before:+--+-- * For CLibName, we unconditionally use the 'PackageIdentifier'.+--+-- * For sub-components, we create a new 'PackageIdentifier' which+-- is encoded in the following way. The test suite "qux" in package+-- "foobar-0.2" gets this package identifier "z-foobar-z-test-qux-0.2".+-- These package IDs have the form:+--+-- cpid ::= "z-" package-id "-z-" component-type "-" component-name+-- component-type ::= "test" | "bench" | "exe" | "lib"+-- package-id and component-name have "-" ( "z" + ) "-"+-- segments encoded by adding an extra "z".+--+-- The mapping for GHC 7.10:+--+-- * For CLibName:+-- If the IPID is of the form foo-0.1-ABCDEF where foo_ABCDEF would+-- validly parse as a package key, we pass "ABCDEF". (NB: not+-- all hashes parse this way, because GHC 7.10 mandated that+-- these hashes be two base-62 encoded 64 bit integers),+-- but hashes that Cabal generated using 'computeComponentId'+-- are guaranteed to have this form.+--+-- If it is not of this form, we rehash the IPID into the+-- correct form and pass that.+--+-- * For sub-components, we rehash the IPID into the correct format+-- and pass that.+--+computeCompatPackageKey+ :: Compiler+ -> PackageIdentifier+ -> ComponentName+ -> UnitId+ -> (PackageName, String)+computeCompatPackageKey comp pid cname uid@(SimpleUnitId (ComponentId str))+ | not (packageKeySupported comp || unitIdSupported comp) =+ -- NB: the package ID in the database entry has to follow this+ let zdashcode s = go s (Nothing :: Maybe Int) []+ where go [] _ r = reverse r+ go ('-':z) (Just n) r | n > 0 = go z (Just 0) ('-':'z':r)+ go ('-':z) _ r = go z (Just 0) ('-':r)+ go ('z':z) (Just n) r = go z (Just (n+1)) ('z':r)+ go (c:z) _ r = go z Nothing (c:r)+ cname_str = case cname of+ CLibName -> error "computeCompatPackageKey"+ CTestName n -> "-z-test-" ++ zdashcode n+ CBenchName n -> "-z-bench-" ++ zdashcode n+ CExeName n -> "-z-exe-" ++ zdashcode n+ package_name+ | cname == CLibName = pkgName pid+ | otherwise = PackageName $ "z-"+ ++ zdashcode (display (pkgName pid))+ ++ zdashcode cname_str+ old_style_key+ | cname == CLibName = display pid+ | otherwise = display package_name ++ "-"+ ++ display (pkgVersion pid)+ in (package_name, old_style_key)+ | not (unifiedIPIDRequired comp) =+ let mb_verbatim_key+ = case simpleParse str :: Maybe PackageId of+ -- Something like 'foo-0.1', use it verbatim.+ -- (NB: hash tags look like tags, so they are parsed,+ -- so the extra equality check tests if a tag was dropped.)+ Just pid0 | display pid0 == str -> Just str+ _ -> Nothing+ mb_truncated_key+ = let cand = reverse (takeWhile isAlphaNum (reverse str))+ in if length cand == 22 && all isAlphaNum cand+ then Just cand+ else Nothing+ rehashed_key = hashToBase62 str+ in (pkgName pid, fromMaybe rehashed_key+ (mb_verbatim_key `mplus` mb_truncated_key))+ | otherwise = (pkgName pid, display uid)++mkComponentsLocalBuildInfo :: ConfigFlags+ -> Compiler+ -> InstalledPackageIndex+ -> PackageDescription+ -> [PackageId] -- internal package deps+ -> [InstalledPackageInfo] -- external package deps+ -> [(Component, [ComponentName])]+ -> FlagAssignment+ -> IO [(ComponentName, ComponentLocalBuildInfo,+ [ComponentName])]+mkComponentsLocalBuildInfo cfg comp installedPackages pkg_descr+ internalPkgDeps externalPkgDeps+ graph flagAssignment = do+ -- Pre-compute library hash so we can setup internal deps+ -- TODO configIPID should have name changed+ let cid = case configIPID cfg of+ Flag cid0 ->+ -- Hack to reuse install dirs machinery+ -- NB: no real IPID available at this point+ let env = packageTemplateEnv (package pkg_descr)+ (mkUnitId "")+ str = fromPathTemplate+ (InstallDirs.substPathTemplate env+ (toPathTemplate cid0))+ in ComponentId str+ _ ->+ computeComponentId (package pkg_descr) CLibName+ (getDeps CLibName) flagAssignment+ uid = SimpleUnitId cid+ (_, compat_key) = computeCompatPackageKey comp+ (package pkg_descr) CLibName uid+ sequence+ [ do clbi <- componentLocalBuildInfo uid compat_key c+ return (componentName c, clbi, cdeps)+ | (c, cdeps) <- graph ]+ where+ getDeps cname =+ let externalPkgs = maybe [] (\lib -> selectSubset+ (componentBuildInfo lib)+ externalPkgDeps)+ (lookupComponent pkg_descr cname)+ in map Installed.installedComponentId externalPkgs++ -- The allPkgDeps contains all the package deps for the whole package+ -- but we need to select the subset for this specific component.+ -- we just take the subset for the package names this component+ -- needs. Note, this only works because we cannot yet depend on two+ -- versions of the same package.+ componentLocalBuildInfo uid compat_key component =+ case component of+ CLib lib -> do+ let exports = map (\n -> Installed.ExposedModule n Nothing)+ (PD.exposedModules lib)+ let mb_reexports = resolveModuleReexports installedPackages+ (packageId pkg_descr)+ uid+ externalPkgDeps lib+ reexports <- case mb_reexports of+ Left problems -> reportModuleReexportProblems problems+ Right r -> return r++ return LibComponentLocalBuildInfo {+ componentPackageDeps = cpds,+ componentUnitId = uid,+ componentCompatPackageKey = compat_key,+ componentPackageRenaming = cprns,+ componentExposedModules = exports ++ reexports+ }+ CExe _ ->+ return ExeComponentLocalBuildInfo {+ componentPackageDeps = cpds,+ componentPackageRenaming = cprns+ }+ CTest _ ->+ return TestComponentLocalBuildInfo {+ componentPackageDeps = cpds,+ componentPackageRenaming = cprns+ }+ CBench _ ->+ return BenchComponentLocalBuildInfo {+ componentPackageDeps = cpds,+ componentPackageRenaming = cprns+ }+ where+ bi = componentBuildInfo component+ dedup = Map.toList . Map.fromList+ cpds = if newPackageDepsBehaviour pkg_descr+ then dedup $+ [ (Installed.installedUnitId pkg, packageId pkg)+ | pkg <- selectSubset bi externalPkgDeps ]+ ++ [ (uid, pkgid)+ | pkgid <- selectSubset bi internalPkgDeps ]+ else [ (Installed.installedUnitId pkg, packageId pkg)+ | pkg <- externalPkgDeps ]+ cprns = if newPackageDepsBehaviour pkg_descr+ then targetBuildRenaming bi+ -- Hack: if we have old package-deps behavior, it's impossible+ -- for non-default renamings to be used, because the Cabal+ -- version is too early. This is a good, because while all the+ -- deps were bundled up in buildDepends, we didn't do this for+ -- renamings, so it's not even clear how to get the merged+ -- version. So just assume that all of them are the default..+ else Map.fromList (map (\(_,pid) ->+ (packageName pid, defaultRenaming)) cpds)++ selectSubset :: Package pkg => BuildInfo -> [pkg] -> [pkg]+ selectSubset bi pkgs =+ [ pkg | pkg <- pkgs, packageName pkg `elem` names bi ]++ names bi = [ name | Dependency name _ <- targetBuildDepends bi ]++-- | Given the author-specified re-export declarations from the .cabal file,+-- resolve them to the form that we need for the package database.+--+-- An invariant of the package database is that we always link the re-export+-- directly to its original defining location (rather than indirectly via a+-- chain of re-exporting packages).+--+resolveModuleReexports :: InstalledPackageIndex+ -> PackageId+ -> UnitId+ -> [InstalledPackageInfo]+ -> Library+ -> Either [(ModuleReexport, String)] -- errors+ [Installed.ExposedModule] -- ok+resolveModuleReexports installedPackages srcpkgid key externalPkgDeps lib =+ case partitionEithers+ (map resolveModuleReexport (PD.reexportedModules lib)) of+ ([], ok) -> Right ok+ (errs, _) -> Left errs+ where+ -- A mapping from visible module names to their original defining+ -- module name. We also record the package name of the package which+ -- *immediately* provided the module (not the original) to handle if the+ -- user explicitly says which build-depends they want to reexport from.+ visibleModules :: Map ModuleName [(PackageName, Installed.ExposedModule)]+ visibleModules =+ Map.fromListWith (++) $+ [ (Installed.exposedName exposedModule, [(exportingPackageName,+ exposedModule)])+ -- The package index here contains all the indirect deps of the+ -- package we're configuring, but we want just the direct deps+ | let directDeps = Set.fromList+ (map Installed.installedUnitId externalPkgDeps)+ , pkg <- PackageIndex.allPackages installedPackages+ , Installed.installedUnitId pkg `Set.member` directDeps+ , let exportingPackageName = packageName pkg+ , exposedModule <- visibleModuleDetails pkg+ ]+ ++ [ (visibleModuleName, [(exportingPackageName, exposedModule)])+ | visibleModuleName <- PD.exposedModules lib+ ++ otherModules (libBuildInfo lib)+ , let exportingPackageName = packageName srcpkgid+ definingModuleName = visibleModuleName+ definingPackageId = key+ originalModule = Installed.OriginalModule definingPackageId+ definingModuleName+ exposedModule = Installed.ExposedModule visibleModuleName+ (Just originalModule)+ ]++ -- All the modules exported from this package and their defining name and+ -- package (either defined here in this package or re-exported from some+ -- other package). Return an ExposedModule because we want to hold onto+ -- signature information.+ visibleModuleDetails :: InstalledPackageInfo -> [Installed.ExposedModule]+ visibleModuleDetails pkg = do+ exposedModule <- Installed.exposedModules pkg+ case Installed.exposedReexport exposedModule of+ -- The first case is the modules actually defined in this package.+ -- In this case the reexport will point to this package.+ Nothing -> return exposedModule {+ Installed.exposedReexport =+ Just (Installed.OriginalModule+ (Installed.installedUnitId pkg)+ (Installed.exposedName exposedModule)) }+ -- On the other hand, a visible module might actually be itself+ -- a re-export! In this case, the re-export info for the package+ -- doing the re-export will point us to the original defining+ -- module name and package, so we can reuse the entry.+ Just _ -> return exposedModule++ resolveModuleReexport reexport@ModuleReexport {+ moduleReexportOriginalPackage = moriginalPackageName,+ moduleReexportOriginalName = originalName,+ moduleReexportName = newName+ } =++ let filterForSpecificPackage =+ case moriginalPackageName of+ Nothing -> id+ Just originalPackageName ->+ filter (\(pkgname, _) -> pkgname == originalPackageName)++ matches = filterForSpecificPackage+ (Map.findWithDefault [] originalName visibleModules)+ in+ case (matches, moriginalPackageName) of+ ((_, exposedModule):rest, _)+ -- TODO: Refine this check for signatures+ | all (\(_, exposedModule') ->+ Installed.exposedReexport exposedModule+ == Installed.exposedReexport exposedModule') rest+ -> Right exposedModule { Installed.exposedName = newName }++ ([], Just originalPackageName)+ -> Left $ (,) reexport+ $ "The package " ++ display originalPackageName+ ++ " does not export a module " ++ display originalName++ ([], Nothing)+ -> Left $ (,) reexport+ $ "The module " ++ display originalName+ ++ " is not exported by any suitable package (this package "+ ++ "itself nor any of its 'build-depends' dependencies)."++ (ms, _)+ -> Left $ (,) reexport+ $ "The module " ++ display originalName ++ " is exported "+ ++ "by more than one package ("+ ++ intercalate ", " [ display pkgname | (pkgname,_) <- ms ]+ ++ ") and so the re-export is ambiguous. The ambiguity can "+ ++ "be resolved by qualifying by the package name. The "+ ++ "syntax is 'packagename:moduleName [as newname]'."++ -- Note: if in future Cabal allows directly depending on multiple+ -- instances of the same package (e.g. backpack) then an additional+ -- ambiguity case is possible here: (_, Just originalPackageName)+ -- with the module being ambiguous despite being qualified by a -- package name. Presumably by that time we'll have a mechanism to -- qualify the instance we're referring to.
Distribution/Simple/GHC.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE PatternGuards #-}+ ----------------------------------------------------------------------------- -- | -- Module : Distribution.Simple.GHC@@ -33,7 +34,10 @@ module Distribution.Simple.GHC ( getGhcInfo,- configure, getInstalledPackages, getPackageDBContents,+ configure,+ getInstalledPackages,+ getInstalledPackagesMonitorFiles,+ getPackageDBContents, buildLib, buildExe, replLib, replExe, startInterpreter,@@ -42,80 +46,59 @@ hcPkgInfo, registerPackage, componentGhcOptions,+ componentCcGhcOptions, getLibDir, isDynamic, getGlobalPackageDB, pkgRoot ) where -import qualified Distribution.Simple.GHC.IPI641 as IPI641+import Control.Applicative -- 7.10 -Werror workaround+import Prelude -- https://ghc.haskell.org/trac/ghc/wiki/Migration/7.10#GHCsaysTheimportof...isredundant+ import qualified Distribution.Simple.GHC.IPI642 as IPI642 import qualified Distribution.Simple.GHC.Internal as Internal import Distribution.Simple.GHC.ImplInfo import Distribution.PackageDescription as PD- ( PackageDescription(..), BuildInfo(..), Executable(..), Library(..)- , allExtensions, libModules, exeModules- , hcOptions, hcSharedOptions, hcProfOptions )-import Distribution.InstalledPackageInfo- ( InstalledPackageInfo )+import Distribution.InstalledPackageInfo (InstalledPackageInfo) import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo- ( InstalledPackageInfo_(..) ) import Distribution.Simple.PackageIndex (InstalledPackageIndex) import qualified Distribution.Simple.PackageIndex as PackageIndex import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), ComponentLocalBuildInfo(..)- , absoluteInstallDirs, depLibraryPaths ) import qualified Distribution.Simple.Hpc as Hpc-import Distribution.Simple.InstallDirs hiding ( absoluteInstallDirs ) import Distribution.Simple.BuildPaths import Distribution.Simple.Utils import Distribution.Package- ( PackageName(..) ) import qualified Distribution.ModuleName as ModuleName import Distribution.Simple.Program- ( Program(..), ConfiguredProgram(..), ProgramConfiguration- , ProgramSearchPath- , rawSystemProgramStdout, rawSystemProgramStdoutConf- , getProgramInvocationOutput, requireProgramVersion, requireProgram- , userMaybeSpecifyPath, programPath, lookupProgram, addKnownProgram- , ghcProgram, ghcPkgProgram, hsc2hsProgram, ldProgram ) import qualified Distribution.Simple.Program.HcPkg as HcPkg import qualified Distribution.Simple.Program.Ar as Ar import qualified Distribution.Simple.Program.Ld as Ld import qualified Distribution.Simple.Program.Strip as Strip import Distribution.Simple.Program.GHC import Distribution.Simple.Setup- ( toFlag, fromFlag, fromFlagOrDefault, configCoverage, configDistPref ) import qualified Distribution.Simple.Setup as Cabal- ( Flag(..) )-import Distribution.Simple.Compiler- ( CompilerFlavor(..), CompilerId(..), Compiler(..), compilerVersion- , PackageDB(..), PackageDBStack, AbiTag(..) )+import Distribution.Simple.Compiler hiding (Flag) import Distribution.Version- ( Version(..), anyVersion, orLaterVersion ) import Distribution.System- ( Platform(..), OS(..) ) import Distribution.Verbosity import Distribution.Text- ( display ) import Distribution.Utils.NubList- ( NubListR, overNubListR, toNubListR )-import Language.Haskell.Extension (Extension(..), KnownExtension(..))+import Language.Haskell.Extension import Control.Monad ( unless, when ) import Data.Char ( isDigit, isSpace ) import Data.List-import qualified Data.Map as M ( fromList )+import qualified Data.Map as M ( fromList, lookup ) import Data.Maybe ( catMaybes )-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid ( Monoid(..) )-#endif+import Data.Monoid as Mon ( Monoid(..) ) import Data.Version ( showVersion ) import System.Directory- ( doesFileExist, getAppUserDataDirectory, createDirectoryIfMissing )-import System.FilePath ( (</>), (<.>), takeExtension,- takeDirectory, replaceExtension,- splitExtension, isRelative )+ ( doesFileExist, getAppUserDataDirectory, createDirectoryIfMissing+ , canonicalizePath )+import System.FilePath ( (</>), (<.>), takeExtension+ , takeDirectory, replaceExtension+ , isRelative ) import qualified System.Info -- -----------------------------------------------------------------------------@@ -146,18 +129,32 @@ ++ programPath ghcProg ++ " is version " ++ display ghcVersion ++ " " ++ programPath ghcPkgProg ++ " is version " ++ display ghcPkgVersion - -- Likewise we try to find the matching hsc2hs program.+ -- Likewise we try to find the matching hsc2hs and haddock programs. let hsc2hsProgram' = hsc2hsProgram { programFindLocation = guessHsc2hsFromGhcPath ghcProg }- conf3 = addKnownProgram hsc2hsProgram' conf2+ haddockProgram' = haddockProgram {+ programFindLocation = guessHaddockFromGhcPath ghcProg+ }+ conf3 = addKnownProgram haddockProgram' $+ addKnownProgram hsc2hsProgram' conf2 languages <- Internal.getLanguages verbosity implInfo ghcProg- extensions <- Internal.getExtensions verbosity implInfo ghcProg+ extensions0 <- Internal.getExtensions verbosity implInfo ghcProg ghcInfo <- Internal.getGhcInfo verbosity implInfo ghcProg let ghcInfoMap = M.fromList ghcInfo + -- starting with GHC 8.0, `TemplateHaskell` will be omitted from+ -- `--supported-extensions` when it's not available.+ -- for older GHCs we can use the "Have interpreter" property to+ -- filter out `TemplateHaskell`+ extensions | ghcVersion < Version [8] []+ , Just "NO" <- M.lookup "Have interpreter" ghcInfoMap+ = filter ((/= EnableExtension TemplateHaskell) . fst)+ extensions0+ | otherwise = extensions0+ let comp = Compiler { compilerId = CompilerId GHC ghcVersion, compilerAbiTag = NoAbiTag,@@ -167,7 +164,8 @@ compilerProperties = ghcInfoMap } compPlatform = Internal.targetPlatform ghcInfo- conf4 = Internal.configureToolchain implInfo ghcProg ghcInfoMap conf3 -- configure gcc and ld+ -- configure gcc and ld+ conf4 = Internal.configureToolchain implInfo ghcProg ghcInfoMap conf3 return (comp, compPlatform, conf4) -- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find@@ -180,30 +178,42 @@ -- guessToolFromGhcPath :: Program -> ConfiguredProgram -> Verbosity -> ProgramSearchPath- -> IO (Maybe FilePath)+ -> IO (Maybe (FilePath, [FilePath])) guessToolFromGhcPath tool ghcProg verbosity searchpath = do let toolname = programName tool- path = programPath ghcProg- dir = takeDirectory path- versionSuffix = takeVersionSuffix (dropExeExtension path)- guessNormal = dir </> toolname <.> exeExtension- guessGhcVersioned = dir </> (toolname ++ "-ghc" ++ versionSuffix)- <.> exeExtension- guessVersioned = dir </> (toolname ++ versionSuffix)- <.> exeExtension- guesses | null versionSuffix = [guessNormal]- | otherwise = [guessGhcVersioned,- guessVersioned,- guessNormal]+ given_path = programPath ghcProg+ given_dir = takeDirectory given_path+ real_path <- canonicalizePath given_path+ let real_dir = takeDirectory real_path+ versionSuffix path = takeVersionSuffix (dropExeExtension path)+ given_suf = versionSuffix given_path+ real_suf = versionSuffix real_path+ guessNormal dir = dir </> toolname <.> exeExtension+ guessGhcVersioned dir suf = dir </> (toolname ++ "-ghc" ++ suf)+ <.> exeExtension+ guessVersioned dir suf = dir </> (toolname ++ suf)+ <.> exeExtension+ mkGuesses dir suf | null suf = [guessNormal dir]+ | otherwise = [guessGhcVersioned dir suf,+ guessVersioned dir suf,+ guessNormal dir]+ guesses = mkGuesses given_dir given_suf +++ if real_path == given_path+ then []+ else mkGuesses real_dir real_suf info verbosity $ "looking for tool " ++ toolname- ++ " near compiler in " ++ dir+ ++ " near compiler in " ++ given_dir+ debug verbosity $ "candidate locations: " ++ show guesses exists <- mapM doesFileExist guesses case [ file | (file, True) <- zip guesses exists ] of -- If we can't find it near ghc, fall back to the usual -- method. [] -> programFindLocation tool verbosity searchpath (fp:_) -> do info verbosity $ "found " ++ toolname ++ " in " ++ fp- return (Just fp)+ let lookedAt = map fst+ . takeWhile (\(_file, exist) -> not exist)+ $ zip guesses exists+ return (Just (fp, lookedAt)) where takeVersionSuffix :: FilePath -> String takeVersionSuffix = takeWhileEndLE isSuffixChar@@ -211,12 +221,6 @@ isSuffixChar :: Char -> Bool isSuffixChar c = isDigit c || c == '.' || c == '-' - dropExeExtension :: FilePath -> FilePath- dropExeExtension filepath =- case splitExtension filepath of- (filepath', extension) | extension == exeExtension -> filepath'- | otherwise -> filepath- -- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find a -- corresponding ghc-pkg, we try looking for both a versioned and unversioned -- ghc-pkg in the same dir, that is:@@ -226,7 +230,8 @@ -- > /usr/local/bin/ghc-pkg(.exe) -- guessGhcPkgFromGhcPath :: ConfiguredProgram- -> Verbosity -> ProgramSearchPath -> IO (Maybe FilePath)+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath])) guessGhcPkgFromGhcPath = guessToolFromGhcPath ghcPkgProgram -- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find a@@ -238,9 +243,23 @@ -- > /usr/local/bin/hsc2hs(.exe) -- guessHsc2hsFromGhcPath :: ConfiguredProgram- -> Verbosity -> ProgramSearchPath -> IO (Maybe FilePath)+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath])) guessHsc2hsFromGhcPath = guessToolFromGhcPath hsc2hsProgram +-- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find a+-- corresponding haddock, we try looking for both a versioned and unversioned+-- haddock in the same dir, that is:+--+-- > /usr/local/bin/haddock-ghc-6.6.1(.exe)+-- > /usr/local/bin/haddock-6.6.1(.exe)+-- > /usr/local/bin/haddock(.exe)+--+guessHaddockFromGhcPath :: ConfiguredProgram+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath]))+guessHaddockFromGhcPath = guessToolFromGhcPath haddockProgram+ getGhcInfo :: Verbosity -> ConfiguredProgram -> IO [(String, String)] getGhcInfo verbosity ghcProg = Internal.getGhcInfo verbosity implInfo ghcProg where@@ -255,11 +274,12 @@ toPackageIndex verbosity pkgss conf -- | Given a package DB stack, return all installed packages.-getInstalledPackages :: Verbosity -> PackageDBStack -> ProgramConfiguration+getInstalledPackages :: Verbosity -> Compiler -> PackageDBStack+ -> ProgramConfiguration -> IO InstalledPackageIndex-getInstalledPackages verbosity packagedbs conf = do+getInstalledPackages verbosity comp packagedbs conf = do checkPackageDbEnvVar- checkPackageDbStack packagedbs+ checkPackageDbStack comp packagedbs pkgss <- getInstalledPackages' verbosity packagedbs conf index <- toPackageIndex verbosity pkgss conf return $! hackRtsPackage index@@ -286,7 +306,7 @@ topDir <- getLibDir' verbosity ghcProg let indices = [ PackageIndex.fromList (map (Internal.substTopDir topDir) pkgs) | (_, pkgs) <- pkgss ]- return $! (mconcat indices)+ return $! mconcat indices where Just ghcProg = lookupProgram ghcProgram conf@@ -309,19 +329,51 @@ dropWhileEndLE isSpace `fmap` rawSystemProgramStdout verbosity ghcProg ["--print-global-package-db"] +-- | Return the 'FilePath' to the per-user GHC package database.+getUserPackageDB :: Verbosity -> ConfiguredProgram -> Platform -> IO FilePath+getUserPackageDB _verbosity ghcProg (Platform arch os) = do+ -- It's rather annoying that we have to reconstruct this, because ghc+ -- hides this information from us otherwise. But for certain use cases+ -- like change monitoring it really can't remain hidden.+ appdir <- getAppUserDataDirectory "ghc"+ return (appdir </> platformAndVersion </> packageConfFileName)+ where+ platformAndVersion = intercalate "-" [ Internal.showArchString arch+ , Internal.showOsString os+ , display ghcVersion ]+ packageConfFileName+ | ghcVersion >= Version [6,12] [] = "package.conf.d"+ | otherwise = "package.conf"+ Just ghcVersion = programVersion ghcProg+ checkPackageDbEnvVar :: IO () checkPackageDbEnvVar = Internal.checkPackageDbEnvVar "GHC" "GHC_PACKAGE_PATH" -checkPackageDbStack :: PackageDBStack -> IO ()-checkPackageDbStack (GlobalPackageDB:rest)+checkPackageDbStack :: Compiler -> PackageDBStack -> IO ()+checkPackageDbStack comp = if flagPackageConf implInfo+ then checkPackageDbStackPre76+ else checkPackageDbStackPost76+ where implInfo = ghcVersionImplInfo (compilerVersion comp)++checkPackageDbStackPost76 :: PackageDBStack -> IO ()+checkPackageDbStackPost76 (GlobalPackageDB:rest) | GlobalPackageDB `notElem` rest = return ()-checkPackageDbStack rest+checkPackageDbStackPost76 rest+ | GlobalPackageDB `elem` rest =+ die $ "If the global package db is specified, it must be "+ ++ "specified first and cannot be specified multiple times"+checkPackageDbStackPost76 _ = return ()++checkPackageDbStackPre76 :: PackageDBStack -> IO ()+checkPackageDbStackPre76 (GlobalPackageDB:rest)+ | GlobalPackageDB `notElem` rest = return ()+checkPackageDbStackPre76 rest | GlobalPackageDB `notElem` rest = die $ "With current ghc versions the global package db is always used "- ++ "and must be listed first. This ghc limitation may be lifted in "- ++ "future, see http://hackage.haskell.org/trac/ghc/ticket/5977"-checkPackageDbStack _ =+ ++ "and must be listed first. This ghc limitation is lifted in GHC 7.6,"+ ++ "see http://hackage.haskell.org/trac/ghc/ticket/5977"+checkPackageDbStackPre76 _ = die $ "If the global package db is specified, it must be " ++ "specified first and cannot be specified multiple times" @@ -372,14 +424,41 @@ = \file content -> case reads content of [(pkgs, _)] -> return (map IPI642.toCurrent pkgs) _ -> failToRead file+ -- We dropped support for 6.4.2 and earlier. | otherwise- = \file content -> case reads content of- [(pkgs, _)] -> return (map IPI641.toCurrent pkgs)- _ -> failToRead file+ = \file _ -> failToRead file Just ghcProg = lookupProgram ghcProgram conf Just ghcVersion = programVersion ghcProg failToRead file = die $ "cannot read ghc package database " ++ file +getInstalledPackagesMonitorFiles :: Verbosity -> Platform+ -> ProgramConfiguration+ -> [PackageDB]+ -> IO [FilePath]+getInstalledPackagesMonitorFiles verbosity platform progdb =+ mapM getPackageDBPath+ where+ getPackageDBPath :: PackageDB -> IO FilePath+ getPackageDBPath GlobalPackageDB =+ selectMonitorFile =<< getGlobalPackageDB verbosity ghcProg++ getPackageDBPath UserPackageDB =+ selectMonitorFile =<< getUserPackageDB verbosity ghcProg platform++ getPackageDBPath (SpecificPackageDB path) = selectMonitorFile path++ -- GHC has old style file dbs, and new style directory dbs.+ -- Note that for dir style dbs, we only need to monitor the cache file, not+ -- the whole directory. The ghc program itself only reads the cache file+ -- so it's safe to only monitor this one file.+ selectMonitorFile path = do+ isFileStyle <- doesFileExist path+ if isFileStyle then return path+ else return (path </> "package.cache")++ Just ghcProg = lookupProgram ghcProgram progdb++ -- ----------------------------------------------------------------------------- -- Building @@ -395,12 +474,10 @@ -> PackageDescription -> LocalBuildInfo -> Library -> ComponentLocalBuildInfo -> IO () buildOrReplLib forRepl verbosity numJobs pkg_descr lbi lib clbi = do- libName <- case componentLibraries clbi of- [libName] -> return libName- [] -> die "No library name found when building library"- _ -> die "Multiple library names found when building library"-- let libTargetDir = buildDir lbi+ let libName = componentUnitId clbi+ libTargetDir+ | componentUnitId clbi == localUnitId lbi = buildDir lbi+ | otherwise = buildDir lbi </> display libName whenVanillaLib forceVanilla = when (forceVanilla || withVanillaLib lbi) whenProfLib = when (withProfLib lbi)@@ -411,11 +488,10 @@ comp = compiler lbi ghcVersion = compilerVersion comp implInfo = getImplInfo comp- (Platform _hostArch hostOS) = hostPlatform lbi- hole_insts = map (\(k,(p,n)) -> (k,(InstalledPackageInfo.packageKey p,n))) (instantiatedWith lbi)+ platform@(Platform _hostArch hostOS) = hostPlatform lbi (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)- let runGhcProg = runGHC verbosity ghcProg comp+ let runGhcProg = runGHC verbosity ghcProg comp platform libBi <- hackThreadedFlag verbosity comp (withProfLib lbi) (libBuildInfo lib)@@ -435,6 +511,7 @@ cname = display $ PD.package $ localPkgDescr lbi distPref = fromFlag $ configDistPref $ configFlags lbi hpcdir way+ | forRepl = Mon.mempty -- HPC is not supported in ghci | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way cname | otherwise = mempty @@ -446,14 +523,14 @@ vanillaOpts = baseOpts `mappend` mempty { ghcOptMode = toFlag GhcModeMake, ghcOptNumJobs = numJobs,- ghcOptPackageKey = toFlag (pkgKey lbi),- ghcOptSigOf = hole_insts, ghcOptInputModules = toNubListR $ libModules lib, ghcOptHPCDir = hpcdir Hpc.Vanilla } profOpts = vanillaOpts `mappend` mempty { ghcOptProfilingMode = toFlag True,+ ghcOptProfilingAuto = Internal.profDetailLevelFlag True+ (withProfLibDetail lbi), ghcOptHiSuffix = toFlag "p_hi", ghcOptObjSuffix = toFlag "p_o", ghcOptExtra = toNubListR $ hcProfOptions GHC libBi,@@ -469,17 +546,20 @@ ghcOptHPCDir = hpcdir Hpc.Dyn } linkerOpts = mempty {- ghcOptLinkOptions = toNubListR $ PD.ldOptions libBi,- ghcOptLinkLibs = toNubListR $ extraLibs libBi,- ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi,- ghcOptLinkFrameworks = toNubListR $ PD.frameworks libBi,+ ghcOptLinkOptions = toNubListR $ PD.ldOptions libBi,+ ghcOptLinkLibs = toNubListR $ extraLibs libBi,+ ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi,+ ghcOptLinkFrameworks = toNubListR $+ PD.frameworks libBi,+ ghcOptLinkFrameworkDirs = toNubListR $+ PD.extraFrameworkDirs libBi, ghcOptInputFiles = toNubListR [libTargetDir </> x | x <- cObjs] } replOpts = vanillaOpts { ghcOptExtra = overNubListR Internal.filterGhciFlags $- (ghcOptExtra vanillaOpts),+ ghcOptExtra vanillaOpts, ghcOptNumJobs = mempty } `mappend` linkerOpts@@ -506,7 +586,7 @@ then do runGhcProg vanillaSharedOpts case (hpcdir Hpc.Dyn, hpcdir Hpc.Vanilla) of- (Cabal.Flag dynDir, Cabal.Flag vanillaDir) -> do+ (Cabal.Flag dynDir, Cabal.Flag vanillaDir) -> -- When the vanilla and shared library builds are done -- in one pass, only one set of HPC module interfaces -- are generated. This set should suffice for both@@ -574,17 +654,17 @@ libInstallPath = libdir $ absoluteInstallDirs pkg_descr lbi NoCopyDest sharedLibInstallPath = libInstallPath </> mkSharedLibName cid libName - stubObjs <- fmap catMaybes $ sequence+ stubObjs <- catMaybes <$> sequence [ findFileWithExtension [objExtension] [libTargetDir] (ModuleName.toFilePath x ++"_stub") | ghcVersion < Version [7,2] [] -- ghc-7.2+ does not make _stub.o files , x <- libModules lib ]- stubProfObjs <- fmap catMaybes $ sequence+ stubProfObjs <- catMaybes <$> sequence [ findFileWithExtension ["p_" ++ objExtension] [libTargetDir] (ModuleName.toFilePath x ++"_stub") | ghcVersion < Version [7,2] [] -- ghc-7.2+ does not make _stub.o files , x <- libModules lib ]- stubSharedObjs <- fmap catMaybes $ sequence+ stubSharedObjs <- catMaybes <$> sequence [ findFileWithExtension ["dyn_" ++ objExtension] [libTargetDir] (ModuleName.toFilePath x ++"_stub") | ghcVersion < Version [7,2] [] -- ghc-7.2+ does not make _stub.o files@@ -593,12 +673,12 @@ hObjs <- Internal.getHaskellObjects implInfo lib lbi libTargetDir objExtension True hProfObjs <-- if (withProfLib lbi)+ if withProfLib lbi then Internal.getHaskellObjects implInfo lib lbi libTargetDir ("p_" ++ objExtension) True else return [] hSharedObjs <-- if (withSharedLib lbi)+ if withSharedLib lbi then Internal.getHaskellObjects implInfo lib lbi libTargetDir ("dyn_" ++ objExtension) False else return []@@ -631,14 +711,15 @@ ghcOptDynLinkMode = toFlag GhcDynamicOnly, ghcOptInputFiles = toNubListR dynamicObjectFiles, ghcOptOutputFile = toFlag sharedLibFilePath,+ ghcOptExtra = toNubListR $+ hcSharedOptions GHC libBi, -- For dynamic libs, Mac OS/X needs to know the install location -- at build time. This only applies to GHC < 7.8 - see the -- discussion in #1660.- ghcOptDylibName = if (hostOS == OSX- && ghcVersion < Version [7,8] [])+ ghcOptDylibName = if hostOS == OSX+ && ghcVersion < Version [7,8] [] then toFlag sharedLibInstallPath else mempty,- ghcOptPackageKey = toFlag (pkgKey lbi), ghcOptNoAutoLinkPackages = toFlag True, ghcOptPackageDBs = withPackageDB lbi, ghcOptPackages = toNubListR $@@ -646,15 +727,17 @@ ghcOptLinkLibs = toNubListR $ extraLibs libBi, ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi, ghcOptLinkFrameworks = toNubListR $ PD.frameworks libBi,+ ghcOptLinkFrameworkDirs =+ toNubListR $ PD.extraFrameworkDirs libBi, ghcOptRPaths = rpaths } info verbosity (show (ghcOptPackages ghcSharedLinkArgs)) - whenVanillaLib False $ do+ whenVanillaLib False $ Ar.createArLibArchive verbosity lbi vanillaLibFilePath staticObjectFiles - whenProfLib $ do+ whenProfLib $ Ar.createArLibArchive verbosity lbi profileLibFilePath profObjectFiles whenGHCiLib $ do@@ -666,16 +749,16 @@ runGhcProg ghcSharedLinkArgs -- | Start a REPL without loading any source files.-startInterpreter :: Verbosity -> ProgramConfiguration -> Compiler+startInterpreter :: Verbosity -> ProgramConfiguration -> Compiler -> Platform -> PackageDBStack -> IO ()-startInterpreter verbosity conf comp packageDBs = do+startInterpreter verbosity conf comp platform packageDBs = do let replOpts = mempty { ghcOptMode = toFlag GhcModeInteractive, ghcOptPackageDBs = packageDBs }- checkPackageDbStack packageDBs+ checkPackageDbStack comp packageDBs (ghcProg, _) <- requireProgram verbosity ghcProgram conf- runGHC verbosity ghcProg comp replOpts+ runGHC verbosity ghcProg comp platform replOpts -- | Build an executable with GHC. --@@ -693,8 +776,9 @@ (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi) let comp = compiler lbi+ platform = hostPlatform lbi implInfo = getImplInfo comp- runGhcProg = runGHC verbosity ghcProg comp+ runGhcProg = runGHC verbosity ghcProg comp platform exeBi <- hackThreadedFlag verbosity comp (withProfExe lbi) (buildInfo exe)@@ -705,7 +789,7 @@ then exeExtension else "") - let targetDir = (buildDir lbi) </> exeName'+ let targetDir = buildDir lbi </> exeName' let exeDir = targetDir </> (exeName' ++ "-tmp") createDirectoryIfMissingVerbose verbosity True targetDir createDirectoryIfMissingVerbose verbosity True exeDir@@ -717,6 +801,7 @@ let isCoverageEnabled = fromFlag $ configCoverage $ configFlags lbi distPref = fromFlag $ configDistPref $ configFlags lbi hpcdir way+ | forRepl = mempty -- HPC is not supported in ghci | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way exeName' | otherwise = mempty @@ -744,9 +829,12 @@ } profOpts = baseOpts `mappend` mempty { ghcOptProfilingMode = toFlag True,+ ghcOptProfilingAuto = Internal.profDetailLevelFlag False+ (withProfExeDetail lbi), ghcOptHiSuffix = toFlag "p_hi", ghcOptObjSuffix = toFlag "p_o",- ghcOptExtra = toNubListR $ hcProfOptions GHC exeBi,+ ghcOptExtra = toNubListR+ (hcProfOptions GHC exeBi), ghcOptHPCDir = hpcdir Hpc.Prof } dynOpts = baseOpts `mappend` mempty {@@ -764,10 +852,13 @@ ghcOptHPCDir = hpcdir Hpc.Dyn } linkerOpts = mempty {- ghcOptLinkOptions = toNubListR $ PD.ldOptions exeBi,- ghcOptLinkLibs = toNubListR $ extraLibs exeBi,- ghcOptLinkLibPath = toNubListR $ extraLibDirs exeBi,- ghcOptLinkFrameworks = toNubListR $ PD.frameworks exeBi,+ ghcOptLinkOptions = toNubListR $ PD.ldOptions exeBi,+ ghcOptLinkLibs = toNubListR $ extraLibs exeBi,+ ghcOptLinkLibPath = toNubListR $ extraLibDirs exeBi,+ ghcOptLinkFrameworks = toNubListR $+ PD.frameworks exeBi,+ ghcOptLinkFrameworkDirs = toNubListR $+ PD.extraFrameworkDirs exeBi, ghcOptInputFiles = toNubListR [exeDir </> x | x <- cObjs] }@@ -816,10 +907,11 @@ | isGhcDynamic = doingTH && (withProfExe lbi || withStaticExe) | otherwise = doingTH && (withProfExe lbi || withDynExe lbi) - linkOpts = commonOpts `mappend`- linkerOpts `mappend`- mempty { ghcOptLinkNoHsMain = toFlag (not isHaskellMain) } `mappend`- (if withDynExe lbi then dynLinkerOpts else mempty)+ linkOpts =+ commonOpts `mappend`+ linkerOpts `mappend`+ mempty { ghcOptLinkNoHsMain = toFlag (not isHaskellMain) } `mappend`+ (if withDynExe lbi then dynLinkerOpts else mempty) -- Build static/dynamic object files for TH, if needed. when compileForTH $@@ -844,7 +936,7 @@ odir = fromFlag (ghcOptObjDir opts) createDirectoryIfMissingVerbose verbosity True odir needsRecomp <- checkNeedsRecompilation filename opts- when needsRecomp $ + when needsRecomp $ runGhcProg opts | filename <- cSrcs ] @@ -908,7 +1000,9 @@ supportRPaths IRIX = False supportRPaths HaLVM = False supportRPaths IOS = False+ supportRPaths Android = False supportRPaths Ghcjs = False+ supportRPaths Hurd = False supportRPaths (OtherOS _) = False -- Do _not_ add a default case so that we get a warning here when a new OS -- is added.@@ -942,11 +1036,11 @@ (compiler lbi) (withProfLib lbi) (libBuildInfo lib) let comp = compiler lbi+ platform = hostPlatform lbi vanillaArgs = (componentGhcOptions verbosity lbi libBi clbi (buildDir lbi)) `mappend` mempty { ghcOptMode = toFlag GhcModeAbiHash,- ghcOptPackageKey = toFlag (pkgKey lbi), ghcOptInputModules = toNubListR $ exposedModules lib } sharedArgs = vanillaArgs `mappend` mempty {@@ -956,19 +1050,23 @@ ghcOptObjSuffix = toFlag "dyn_o", ghcOptExtra = toNubListR $ hcSharedOptions GHC libBi }- profArgs = vanillaArgs `mappend` mempty {+ profArgs = vanillaArgs `mappend` mempty { ghcOptProfilingMode = toFlag True,+ ghcOptProfilingAuto = Internal.profDetailLevelFlag True+ (withProfLibDetail lbi), ghcOptHiSuffix = toFlag "p_hi", ghcOptObjSuffix = toFlag "p_o", ghcOptExtra = toNubListR $ hcProfOptions GHC libBi- }- ghcArgs = if withVanillaLib lbi then vanillaArgs- else if withSharedLib lbi then sharedArgs- else if withProfLib lbi then profArgs- else error "libAbiHash: Can't find an enabled library way"- --+ }+ ghcArgs+ | withVanillaLib lbi = vanillaArgs+ | withSharedLib lbi = sharedArgs+ | withProfLib lbi = profArgs+ | otherwise = error "libAbiHash: Can't find an enabled library way"+ (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)- hash <- getProgramInvocationOutput verbosity (ghcInvocation ghcProg comp ghcArgs)+ hash <- getProgramInvocationOutput verbosity+ (ghcInvocation ghcProg comp platform ghcArgs) return (takeWhile (not . isSpace) hash) componentGhcOptions :: Verbosity -> LocalBuildInfo@@ -976,6 +1074,16 @@ -> GhcOptions componentGhcOptions = Internal.componentGhcOptions +componentCcGhcOptions :: Verbosity -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo+ -> FilePath -> FilePath+ -> GhcOptions+componentCcGhcOptions verbosity lbi =+ Internal.componentCcGhcOptions verbosity implInfo lbi+ where+ comp = compiler lbi+ implInfo = getImplInfo comp+ -- ----------------------------------------------------------------------------- -- Installing @@ -1020,22 +1128,24 @@ whenShared $ copyModuleFiles "dyn_hi" -- copy the built library files over:- whenVanilla $ mapM_ (installOrdinary builtDir targetDir) vanillaLibNames- whenProf $ mapM_ (installOrdinary builtDir targetDir) profileLibNames- whenGHCi $ mapM_ (installOrdinary builtDir targetDir) ghciLibNames- whenShared $ mapM_ (installShared builtDir dynlibTargetDir) sharedLibNames+ whenVanilla $ installOrdinary builtDir targetDir vanillaLibName+ whenProf $ installOrdinary builtDir targetDir profileLibName+ whenGHCi $ installOrdinary builtDir targetDir ghciLibName+ whenShared $ installShared builtDir dynlibTargetDir sharedLibName where install isShared srcDir dstDir name = do let src = srcDir </> name dst = dstDir </> name createDirectoryIfMissingVerbose verbosity True dstDir+ if isShared- then do when (stripLibs lbi) $ Strip.stripLib verbosity- (hostPlatform lbi) (withPrograms lbi) src- installExecutableFile verbosity src dst+ then installExecutableFile verbosity src dst else installOrdinaryFile verbosity src dst + when (stripLibs lbi) $ Strip.stripLib verbosity+ (hostPlatform lbi) (withPrograms lbi) dst+ installOrdinary = install False installShared = install True @@ -1044,11 +1154,11 @@ >>= installOrdinaryFiles verbosity targetDir cid = compilerId (compiler lbi)- libNames = componentLibraries clbi- vanillaLibNames = map mkLibName libNames- profileLibNames = map mkProfLibName libNames- ghciLibNames = map Internal.mkGHCiLibName libNames- sharedLibNames = map (mkSharedLibName cid) libNames+ libName = componentUnitId clbi+ vanillaLibName = mkLibName libName+ profileLibName = mkProfLibName libName+ ghciLibName = Internal.mkGHCiLibName libName+ sharedLibName = (mkSharedLibName cid) libName hasLib = not $ null (libModules lib) && null (cSources (libBuildInfo lib))@@ -1065,7 +1175,10 @@ , HcPkg.noPkgDbStack = v < [6,9] , HcPkg.noVerboseFlag = v < [6,11] , HcPkg.flagPackageConf = v < [7,5]- , HcPkg.useSingleFileDb = v < [7,9]+ , HcPkg.supportsDirDbs = v >= [6,8]+ , HcPkg.requiresDirDbs = v >= [7,10]+ , HcPkg.nativeMultiInstance = v >= [7,10]+ , HcPkg.recacheMultiInstance = v >= [6,12] } where v = versionBranch ver@@ -1074,16 +1187,20 @@ registerPackage :: Verbosity- -> InstalledPackageInfo- -> PackageDescription- -> LocalBuildInfo+ -> ProgramConfiguration -> Bool -> PackageDBStack+ -> InstalledPackageInfo -> IO ()-registerPackage verbosity installedPkgInfo _pkg lbi _inplace packageDbs =- HcPkg.reregister (hcPkgInfo $ withPrograms lbi) verbosity- packageDbs (Right installedPkgInfo)+registerPackage verbosity progdb multiInstance packageDbs installedPkgInfo+ | multiInstance+ = HcPkg.registerMultiInstance (hcPkgInfo progdb) verbosity+ packageDbs installedPkgInfo + | otherwise+ = HcPkg.reregister (hcPkgInfo progdb) verbosity+ packageDbs (Right installedPkgInfo)+ pkgRoot :: Verbosity -> LocalBuildInfo -> PackageDB -> IO FilePath pkgRoot verbosity lbi = pkgRoot' where@@ -1093,7 +1210,8 @@ pkgRoot' UserPackageDB = do appDir <- getAppUserDataDirectory "ghc" let ver = compilerVersion (compiler lbi)- subdir = System.Info.arch ++ '-':System.Info.os ++ '-':showVersion ver+ subdir = System.Info.arch ++ '-':System.Info.os+ ++ '-':showVersion ver rootDir = appDir </> subdir -- We must create the root directory for the user package database if it -- does not yet exists. Otherwise '${pkgroot}' will resolve to a
− Distribution/Simple/GHC/IPI641.hs
@@ -1,106 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.GHC.IPI641--- Copyright : (c) The University of Glasgow 2004--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable-----module Distribution.Simple.GHC.IPI641 (- InstalledPackageInfo(..),- toCurrent,- ) where--import qualified Distribution.InstalledPackageInfo as Current-import qualified Distribution.Package as Current hiding (depends, installedPackageId)-import Distribution.Text (display)--import Distribution.Simple.GHC.IPI642- ( PackageIdentifier, convertPackageId- , License, convertLicense, convertModuleName )---- | This is the InstalledPackageInfo type used by ghc-6.4 and 6.4.1.------ It's here purely for the 'Read' instance so that we can read the package--- database used by those ghc versions. It is a little hacky to read the--- package db directly, but we do need the info and until ghc-6.9 there was--- no better method.------ In ghc-6.4.2 the format changed a bit. See "Distribution.Simple.GHC.IPI642"----data InstalledPackageInfo = InstalledPackageInfo {- package :: PackageIdentifier,- license :: License,- copyright :: String,- maintainer :: String,- author :: String,- stability :: String,- homepage :: String,- pkgUrl :: String,- description :: String,- category :: String,- exposed :: Bool,- exposedModules :: [String],- hiddenModules :: [String],- importDirs :: [FilePath],- libraryDirs :: [FilePath],- hsLibraries :: [String],- extraLibraries :: [String],- includeDirs :: [FilePath],- includes :: [String],- depends :: [PackageIdentifier],- hugsOptions :: [String],- ccOptions :: [String],- ldOptions :: [String],- frameworkDirs :: [FilePath],- frameworks :: [String],- haddockInterfaces :: [FilePath],- haddockHTMLs :: [FilePath]- }- deriving Read--mkInstalledPackageId :: Current.PackageIdentifier -> Current.InstalledPackageId-mkInstalledPackageId = Current.InstalledPackageId . display--toCurrent :: InstalledPackageInfo -> Current.InstalledPackageInfo-toCurrent ipi@InstalledPackageInfo{} =- let pid = convertPackageId (package ipi)- mkExposedModule m = Current.ExposedModule m Nothing Nothing- in Current.InstalledPackageInfo {- Current.installedPackageId = mkInstalledPackageId (convertPackageId (package ipi)),- Current.sourcePackageId = pid,- Current.packageKey = Current.OldPackageKey pid,- Current.license = convertLicense (license ipi),- Current.copyright = copyright ipi,- Current.maintainer = maintainer ipi,- Current.author = author ipi,- Current.stability = stability ipi,- Current.homepage = homepage ipi,- Current.pkgUrl = pkgUrl ipi,- Current.synopsis = "",- Current.description = description ipi,- Current.category = category ipi,- Current.exposed = exposed ipi,- Current.exposedModules = map (mkExposedModule . convertModuleName) (exposedModules ipi),- Current.instantiatedWith = [],- Current.hiddenModules = map convertModuleName (hiddenModules ipi),- Current.trusted = Current.trusted Current.emptyInstalledPackageInfo,- Current.importDirs = importDirs ipi,- Current.libraryDirs = libraryDirs ipi,- Current.dataDir = "",- Current.hsLibraries = hsLibraries ipi,- Current.extraLibraries = extraLibraries ipi,- Current.extraGHCiLibraries = [],- Current.includeDirs = includeDirs ipi,- Current.includes = includes ipi,- Current.depends = map (mkInstalledPackageId.convertPackageId) (depends ipi),- Current.ccOptions = ccOptions ipi,- Current.ldOptions = ldOptions ipi,- Current.frameworkDirs = frameworkDirs ipi,- Current.frameworks = frameworks ipi,- Current.haddockInterfaces = haddockInterfaces ipi,- Current.haddockHTMLs = haddockHTMLs ipi,- Current.pkgRoot = Nothing- }
Distribution/Simple/GHC/IPI642.hs view
@@ -11,22 +11,11 @@ module Distribution.Simple.GHC.IPI642 ( InstalledPackageInfo(..), toCurrent,-- -- Don't use these, they're only for conversion purposes- PackageIdentifier, convertPackageId,- License, convertLicense,- convertModuleName ) where import qualified Distribution.InstalledPackageInfo as Current-import qualified Distribution.Package as Current hiding (depends, installedPackageId)-import qualified Distribution.License as Current--import Distribution.Version (Version)-import Distribution.ModuleName (ModuleName)-import Distribution.Text (simpleParse,display)--import Data.Maybe+import qualified Distribution.Package as Current hiding (installedUnitId)+import Distribution.Simple.GHC.IPIConvert -- | This is the InstalledPackageInfo type used by ghc-6.4.2 and later. --@@ -70,43 +59,15 @@ } deriving Read -data PackageIdentifier = PackageIdentifier {- pkgName :: String,- pkgVersion :: Version- }- deriving Read--data License = GPL | LGPL | BSD3 | BSD4- | PublicDomain | AllRightsReserved | OtherLicense- deriving Read--convertPackageId :: PackageIdentifier -> Current.PackageIdentifier-convertPackageId PackageIdentifier { pkgName = n, pkgVersion = v } =- Current.PackageIdentifier (Current.PackageName n) v--mkInstalledPackageId :: Current.PackageIdentifier -> Current.InstalledPackageId-mkInstalledPackageId = Current.InstalledPackageId . display--convertModuleName :: String -> ModuleName-convertModuleName s = fromJust $ simpleParse s--convertLicense :: License -> Current.License-convertLicense GPL = Current.GPL Nothing-convertLicense LGPL = Current.LGPL Nothing-convertLicense BSD3 = Current.BSD3-convertLicense BSD4 = Current.BSD4-convertLicense PublicDomain = Current.PublicDomain-convertLicense AllRightsReserved = Current.AllRightsReserved-convertLicense OtherLicense = Current.OtherLicense- toCurrent :: InstalledPackageInfo -> Current.InstalledPackageInfo toCurrent ipi@InstalledPackageInfo{} = let pid = convertPackageId (package ipi)- mkExposedModule m = Current.ExposedModule m Nothing Nothing+ mkExposedModule m = Current.ExposedModule m Nothing in Current.InstalledPackageInfo {- Current.installedPackageId = mkInstalledPackageId (convertPackageId (package ipi)), Current.sourcePackageId = pid,- Current.packageKey = Current.OldPackageKey pid,+ Current.installedUnitId = Current.mkLegacyUnitId pid,+ Current.compatPackageKey = "",+ Current.abiHash = Current.AbiHash "", -- bogus but old GHCs don't care. Current.license = convertLicense (license ipi), Current.copyright = copyright ipi, Current.maintainer = maintainer ipi,@@ -120,7 +81,6 @@ Current.exposed = exposed ipi, Current.exposedModules = map (mkExposedModule . convertModuleName) (exposedModules ipi), Current.hiddenModules = map convertModuleName (hiddenModules ipi),- Current.instantiatedWith = [], Current.trusted = Current.trusted Current.emptyInstalledPackageInfo, Current.importDirs = importDirs ipi, Current.libraryDirs = libraryDirs ipi,@@ -130,7 +90,7 @@ Current.extraGHCiLibraries = extraGHCiLibraries ipi, Current.includeDirs = includeDirs ipi, Current.includes = includes ipi,- Current.depends = map (mkInstalledPackageId.convertPackageId) (depends ipi),+ Current.depends = map (Current.mkLegacyUnitId . convertPackageId) (depends ipi), Current.ccOptions = ccOptions ipi, Current.ldOptions = ldOptions ipi, Current.frameworkDirs = frameworkDirs ipi,
+ Distribution/Simple/GHC/IPIConvert.hs view
@@ -0,0 +1,50 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.GHC.IPI642+-- Copyright : (c) The University of Glasgow 2004+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Helper functions for 'Distribution.Simple.GHC.IPI642'.+module Distribution.Simple.GHC.IPIConvert (+ PackageIdentifier, convertPackageId,+ License, convertLicense,+ convertModuleName+ ) where++import qualified Distribution.Package as Current hiding (installedUnitId)+import qualified Distribution.License as Current++import Distribution.Version+import Distribution.ModuleName+import Distribution.Text++import Data.Maybe++data PackageIdentifier = PackageIdentifier {+ pkgName :: String,+ pkgVersion :: Version+ }+ deriving Read++convertPackageId :: PackageIdentifier -> Current.PackageIdentifier+convertPackageId PackageIdentifier { pkgName = n, pkgVersion = v } =+ Current.PackageIdentifier (Current.PackageName n) v++data License = GPL | LGPL | BSD3 | BSD4+ | PublicDomain | AllRightsReserved | OtherLicense+ deriving Read++convertModuleName :: String -> ModuleName+convertModuleName s = fromJust $ simpleParse s++convertLicense :: License -> Current.License+convertLicense GPL = Current.GPL Nothing+convertLicense LGPL = Current.LGPL Nothing+convertLicense BSD3 = Current.BSD3+convertLicense BSD4 = Current.BSD4+convertLicense PublicDomain = Current.PublicDomain+convertLicense AllRightsReserved = Current.AllRightsReserved+convertLicense OtherLicense = Current.OtherLicense
Distribution/Simple/GHC/ImplInfo.hs view
@@ -15,9 +15,7 @@ ) where import Distribution.Simple.Compiler- ( Compiler(..), CompilerFlavor(..)- , compilerFlavor, compilerVersion, compilerCompatVersion )-import Distribution.Version ( Version(..) )+import Distribution.Version {- | Information about features and quirks of a GHC-based implementation.@@ -47,6 +45,7 @@ , reportsNoExt :: Bool -- ^ --supported-languages gives Ext and NoExt , alwaysNondecIndent :: Bool -- ^ NondecreasingIndentation is always on , flagGhciScript :: Bool -- ^ -ghci-script flag supported+ , flagProfAuto :: Bool -- ^ new style -fprof-auto* flags , flagPackageConf :: Bool -- ^ use package-conf instead of package-db , flagDebugInfo :: Bool -- ^ -g flag supported }@@ -80,6 +79,7 @@ , reportsNoExt = v >= [7] , alwaysNondecIndent = v < [7,1] , flagGhciScript = v >= [7,2]+ , flagProfAuto = v >= [7,4] , flagPackageConf = v < [7,5] , flagDebugInfo = v >= [7,10] }@@ -100,6 +100,7 @@ , reportsNoExt = True , alwaysNondecIndent = False , flagGhciScript = True+ , flagProfAuto = True , flagPackageConf = False , flagDebugInfo = False }
Distribution/Simple/GHC/Internal.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE PatternGuards #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Simple.GHC.Internal@@ -24,55 +24,42 @@ getHaskellObjects, mkGhcOptPackages, substTopDir,- checkPackageDbEnvVar+ checkPackageDbEnvVar,+ profDetailLevelFlag,+ showArchString,+ showOsString, ) where -import Distribution.Simple.GHC.ImplInfo ( GhcImplInfo (..) )+import Distribution.Simple.GHC.ImplInfo import Distribution.Package- ( InstalledPackageId, PackageId ) import Distribution.InstalledPackageInfo- ( InstalledPackageInfo ) import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo- ( InstalledPackageInfo_(..) )-import Distribution.PackageDescription as PD- ( BuildInfo(..), Library(..), libModules- , hcOptions, usedExtensions, ModuleRenaming, lookupRenaming )-import Distribution.Compat.Exception ( catchExit, catchIO )-import Distribution.Simple.Compiler- ( CompilerFlavor(..), Compiler(..), DebugInfoLevel(..), OptimisationLevel(..) )+import Distribution.PackageDescription as PD hiding (Flag)+import Distribution.Compat.Exception+import Distribution.Lex+import Distribution.Simple.Compiler hiding (Flag) import Distribution.Simple.Program.GHC import Distribution.Simple.Setup- ( toFlag ) import qualified Distribution.ModuleName as ModuleName import Distribution.Simple.Program- ( Program(..), ConfiguredProgram(..), ProgramConfiguration- , ProgramLocation(..), ProgramSearchPath, ProgramSearchPathEntry(..)- , rawSystemProgram, rawSystemProgramStdout, programPath- , addKnownProgram, arProgram, ldProgram, gccProgram, stripProgram- , getProgramOutput )-import Distribution.Simple.Program.Types ( suppressOverrideArgs ) import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), ComponentLocalBuildInfo(..)- , LibraryName(..) ) import Distribution.Simple.Utils import Distribution.Simple.BuildPaths-import Distribution.System ( buildOS, OS(..), Platform, platformFromTriple )+import Distribution.System import Distribution.Text ( display, simpleParse ) import Distribution.Utils.NubList ( toNubListR ) import Distribution.Verbosity import Language.Haskell.Extension- ( Language(..), Extension(..), KnownExtension(..) ) import qualified Data.Map as M import Data.Char ( isSpace ) import Data.Maybe ( fromMaybe, maybeToList, isJust ) import Control.Monad ( unless, when )-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid ( Monoid(..) )-#endif+import Data.Monoid as Mon ( Monoid(..) ) import System.Directory ( getDirectoryContents, getTemporaryDirectory ) import System.Environment ( getEnv )-import System.FilePath ( (</>), (<.>), takeExtension, takeDirectory )+import System.FilePath ( (</>), (<.>), takeExtension+ , takeDirectory, takeFileName) import System.IO ( hClose, hPutStrLn ) targetPlatform :: [(String, String)] -> Maybe Platform@@ -87,18 +74,18 @@ -> ProgramConfiguration configureToolchain implInfo ghcProg ghcInfo = addKnownProgram gccProgram {- programFindLocation = findProg gccProgram extraGccPath,+ programFindLocation = findProg gccProgramName extraGccPath, programPostConf = configureGcc } . addKnownProgram ldProgram {- programFindLocation = findProg ldProgram extraLdPath,+ programFindLocation = findProg ldProgramName extraLdPath, programPostConf = configureLd } . addKnownProgram arProgram {- programFindLocation = findProg arProgram extraArPath+ programFindLocation = findProg arProgramName extraArPath } . addKnownProgram stripProgram {- programFindLocation = findProg stripProgram extraStripPath+ programFindLocation = findProg stripProgramName extraStripPath } where compilerDir = takeDirectory (programPath ghcProg)@@ -109,6 +96,14 @@ isWindows = case buildOS of Windows -> True; _ -> False binPrefix = "" + maybeName :: Program -> Maybe FilePath -> String+ maybeName prog = maybe (programName prog) (dropExeExtension . takeFileName)++ gccProgramName = maybeName gccProgram mbGccLocation+ ldProgramName = maybeName ldProgram mbLdLocation+ arProgramName = maybeName arProgram mbArLocation+ stripProgramName = maybeName stripProgram mbStripLocation+ mkExtraPath :: Maybe FilePath -> FilePath -> [FilePath] mkExtraPath mbPath mingwPath | isWindows = mbDir ++ [mingwPath] | otherwise = mbDir@@ -128,10 +123,11 @@ let b = mingwBinDir </> binPrefix in (b, b, b, b) - findProg :: Program -> [FilePath]- -> Verbosity -> ProgramSearchPath -> IO (Maybe FilePath)- findProg prog extraPath v searchpath =- programFindLocation prog v searchpath'+ findProg :: String -> [FilePath]+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath]))+ findProg progName extraPath v searchpath =+ findProgramOnSearchPath v searchpath' progName where searchpath' = (map ProgramSearchPathDir extraPath) ++ searchpath @@ -146,12 +142,19 @@ gccLinkerFlags = getFlags "Gcc Linker flags" ldLinkerFlags = getFlags "Ld Linker flags" - getFlags key = case M.lookup key ghcInfo of- Nothing -> []- Just flags ->- case reads flags of- [(args, "")] -> args- _ -> [] -- XXX Should should be an error really+ -- It appears that GHC 7.6 and earlier encode the tokenized flags as a+ -- [String] in these settings whereas later versions just encode the flags as+ -- String.+ --+ -- We first try to parse as a [String] and if this fails then tokenize the+ -- flags ourself.+ getFlags :: String -> [String]+ getFlags key =+ case M.lookup key ghcInfo of+ Nothing -> []+ Just flags+ | (flags', ""):_ <- reads flags -> flags'+ | otherwise -> tokenizeQuotedWords flags configureGcc :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram configureGcc v gccProg = do@@ -363,6 +366,10 @@ ghcOptVerbosity = toFlag verbosity, ghcOptHideAllPackages = toFlag True, ghcOptCabal = toFlag True,+ ghcOptThisUnitId = case clbi of+ LibComponentLocalBuildInfo { componentCompatPackageKey = pk }+ -> toFlag pk+ _ -> Mon.mempty, ghcOptPackageDBs = withPackageDB lbi, ghcOptPackages = toNubListR $ mkGhcOptPackages clbi, ghcOptSplitObjs = toFlag (splitObjs lbi),@@ -411,8 +418,8 @@ supported "-unreg" = False supported _ = True -mkGHCiLibName :: LibraryName -> String-mkGHCiLibName (LibraryName lib) = lib <.> "o"+mkGHCiLibName :: UnitId -> String+mkGHCiLibName lib = getHSLibraryName lib <.> "o" ghcLookupProperty :: String -> Compiler -> Bool ghcLookupProperty prop comp =@@ -442,7 +449,7 @@ | x <- libModules lib ] mkGhcOptPackages :: ComponentLocalBuildInfo- -> [(InstalledPackageId, PackageId, ModuleRenaming)]+ -> [(UnitId, PackageId, ModuleRenaming)] mkGhcOptPackages clbi = map (\(i,p) -> (i,p,lookupRenaming p (componentPackageRenaming clbi))) (componentPackageDeps clbi)@@ -484,9 +491,38 @@ unless (mPP == mcsPP) abort where lookupEnv :: String -> IO (Maybe String)- lookupEnv name = (Just `fmap` getEnv name) `catchIO` const (return Nothing)+ lookupEnv name = (Just `fmap` getEnv name)+ `catchIO` const (return Nothing) abort = die $ "Use of " ++ compilerName ++ "'s environment variable " ++ packagePathEnvVar ++ " is incompatible with Cabal. Use the " ++ "flag --package-db to specify a package database (it can be " ++ "used multiple times)."++profDetailLevelFlag :: Bool -> ProfDetailLevel -> Flag GhcProfAuto+profDetailLevelFlag forLib mpl =+ case mpl of+ ProfDetailNone -> mempty+ ProfDetailDefault | forLib -> toFlag GhcProfAutoExported+ | otherwise -> toFlag GhcProfAutoToplevel+ ProfDetailExportedFunctions -> toFlag GhcProfAutoExported+ ProfDetailToplevelFunctions -> toFlag GhcProfAutoToplevel+ ProfDetailAllFunctions -> toFlag GhcProfAutoAll+ ProfDetailOther _ -> mempty++-- | GHC's rendering of it's host or target 'Arch' as used in its platform+-- strings and certain file locations (such as user package db location).+--+showArchString :: Arch -> String+showArchString PPC = "powerpc"+showArchString PPC64 = "powerpc64"+showArchString other = display other++-- | GHC's rendering of it's host or target 'OS' as used in its platform+-- strings and certain file locations (such as user package db location).+--+showOsString :: OS -> String+showOsString Windows = "mingw32"+showOsString OSX = "darwin"+showOsString Solaris = "solaris2"+showOsString other = display other
Distribution/Simple/GHCJS.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE CPP #-}- module Distribution.Simple.GHCJS ( configure, getInstalledPackages, getPackageDBContents, buildLib, buildExe,@@ -16,70 +14,40 @@ runCmd ) where -import Distribution.Simple.GHC.ImplInfo ( getImplInfo, ghcjsVersionImplInfo )+import Distribution.Simple.GHC.ImplInfo import qualified Distribution.Simple.GHC.Internal as Internal import Distribution.PackageDescription as PD- ( PackageDescription(..), BuildInfo(..), Executable(..)- , Library(..), libModules, exeModules- , hcOptions, hcProfOptions, hcSharedOptions- , allExtensions ) import Distribution.InstalledPackageInfo- ( InstalledPackageInfo )-import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo- ( InstalledPackageInfo_(..) )+import Distribution.Package import Distribution.Simple.PackageIndex ( InstalledPackageIndex ) import qualified Distribution.Simple.PackageIndex as PackageIndex import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), ComponentLocalBuildInfo(..)- , LibraryName(..) ) import qualified Distribution.Simple.Hpc as Hpc-import Distribution.Simple.InstallDirs hiding ( absoluteInstallDirs ) import Distribution.Simple.BuildPaths import Distribution.Simple.Utils import Distribution.Simple.Program- ( Program(..), ConfiguredProgram(..), ProgramConfiguration- , ProgramSearchPath- , rawSystemProgramConf- , rawSystemProgramStdout, rawSystemProgramStdoutConf- , getProgramInvocationOutput- , requireProgramVersion, requireProgram- , userMaybeSpecifyPath, programPath- , lookupProgram, addKnownPrograms- , ghcjsProgram, ghcjsPkgProgram, c2hsProgram, hsc2hsProgram- , ldProgram, haddockProgram, stripProgram ) import qualified Distribution.Simple.Program.HcPkg as HcPkg import qualified Distribution.Simple.Program.Ar as Ar import qualified Distribution.Simple.Program.Ld as Ld import qualified Distribution.Simple.Program.Strip as Strip import Distribution.Simple.Program.GHC-import Distribution.Simple.Setup- ( toFlag, fromFlag, configCoverage, configDistPref )+import Distribution.Simple.Setup hiding ( Flag ) import qualified Distribution.Simple.Setup as Cabal- ( Flag(..) )-import Distribution.Simple.Compiler- ( CompilerFlavor(..), CompilerId(..), Compiler(..)- , PackageDB(..), PackageDBStack, AbiTag(..) )+import Distribution.Simple.Compiler hiding ( Flag ) import Distribution.Version- ( Version(..), anyVersion, orLaterVersion ) import Distribution.System- ( Platform(..) ) import Distribution.Verbosity import Distribution.Utils.NubList- ( overNubListR, toNubListR )-import Distribution.Text ( display )-import Language.Haskell.Extension ( Extension(..)- , KnownExtension(..))+import Distribution.Text+import Language.Haskell.Extension import Control.Monad ( unless, when ) import Data.Char ( isSpace ) import qualified Data.Map as M ( fromList )-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid ( Monoid(..) )-#endif+import Data.Monoid as Mon ( Monoid(..) ) import System.Directory ( doesFileExist )-import System.FilePath ( (</>), (<.>), takeExtension,- takeDirectory, replaceExtension,- splitExtension )+import System.FilePath ( (</>), (<.>), takeExtension+ , takeDirectory, replaceExtension ) configure :: Verbosity -> Maybe FilePath -> Maybe FilePath -> ProgramConfiguration@@ -156,24 +124,24 @@ ghcjsNativeToo = Internal.ghcLookupProperty "Native Too" guessGhcjsPkgFromGhcjsPath :: ConfiguredProgram -> Verbosity- -> ProgramSearchPath -> IO (Maybe FilePath)+ -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath])) guessGhcjsPkgFromGhcjsPath = guessToolFromGhcjsPath ghcjsPkgProgram guessHsc2hsFromGhcjsPath :: ConfiguredProgram -> Verbosity- -> ProgramSearchPath -> IO (Maybe FilePath)+ -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath])) guessHsc2hsFromGhcjsPath = guessToolFromGhcjsPath hsc2hsProgram guessC2hsFromGhcjsPath :: ConfiguredProgram -> Verbosity- -> ProgramSearchPath -> IO (Maybe FilePath)+ -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath])) guessC2hsFromGhcjsPath = guessToolFromGhcjsPath c2hsProgram guessHaddockFromGhcjsPath :: ConfiguredProgram -> Verbosity- -> ProgramSearchPath -> IO (Maybe FilePath)+ -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath])) guessHaddockFromGhcjsPath = guessToolFromGhcjsPath haddockProgram guessToolFromGhcjsPath :: Program -> ConfiguredProgram -> Verbosity -> ProgramSearchPath- -> IO (Maybe FilePath)+ -> IO (Maybe (FilePath, [FilePath])) guessToolFromGhcjsPath tool ghcjsProg verbosity searchpath = do let toolname = programName tool path = programPath ghcjsProg@@ -198,19 +166,15 @@ -- method. [] -> programFindLocation tool verbosity searchpath (fp:_) -> do info verbosity $ "found " ++ toolname ++ " in " ++ fp- return (Just fp)+ let lookedAt = map fst+ . takeWhile (\(_file, exist) -> not exist)+ $ zip guesses exists+ return (Just (fp, lookedAt)) where takeVersionSuffix :: FilePath -> String takeVersionSuffix = reverse . takeWhile (`elem ` "0123456789.-") . reverse - dropExeExtension :: FilePath -> FilePath- dropExeExtension filepath =- case splitExtension filepath of- (filepath', extension) | extension == exeExtension -> filepath'- | otherwise -> filepath-- -- | Given a single package DB, return all installed packages. getPackageDBContents :: Verbosity -> PackageDB -> ProgramConfiguration -> IO InstalledPackageIndex@@ -302,11 +266,8 @@ -> PackageDescription -> LocalBuildInfo -> Library -> ComponentLocalBuildInfo -> IO () buildOrReplLib forRepl verbosity numJobs _pkg_descr lbi lib clbi = do- libName <- case componentLibraries clbi of- [libName] -> return libName- [] -> die "No library name found when building library"- _ -> die "Multiple library names found when building library"- let libTargetDir = buildDir lbi+ let libName = componentUnitId clbi+ libTargetDir = buildDir lbi whenVanillaLib forceVanilla = when (not forRepl && (forceVanilla || withVanillaLib lbi)) whenProfLib = when (not forRepl && withProfLib lbi)@@ -314,14 +275,13 @@ when (not forRepl && (forceShared || withSharedLib lbi)) whenGHCiLib = when (not forRepl && withGHCiLib lbi && withVanillaLib lbi) ifReplLib = when forRepl- comp = compiler lbi- implInfo = getImplInfo comp- hole_insts = map (\(k,(p,n)) -> (k,(InstalledPackageInfo.packageKey p,n)))- (instantiatedWith lbi)+ comp = compiler lbi+ platform = hostPlatform lbi+ implInfo = getImplInfo comp nativeToo = ghcjsNativeToo comp (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi)- let runGhcjsProg = runGHC verbosity ghcjsProg comp+ let runGhcjsProg = runGHC verbosity ghcjsProg comp platform libBi = libBuildInfo lib isGhcjsDynamic = isDynamic comp dynamicTooSupported = supportsDynamicToo comp@@ -339,7 +299,7 @@ distPref = fromFlag $ configDistPref $ configFlags lbi hpcdir way | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way cname- | otherwise = mempty+ | otherwise = Mon.mempty createDirectoryIfMissingVerbose verbosity True libTargetDir -- TODO: do we need to put hs-boot files into place for mutually recursive@@ -349,15 +309,13 @@ baseOpts = componentGhcOptions verbosity lbi libBi clbi libTargetDir linkJsLibOpts = mempty { ghcOptExtra = toNubListR $- [ "-link-js-lib" , (\(LibraryName l) -> l) libName+ [ "-link-js-lib" , getHSLibraryName libName , "-js-lib-outputdir", libTargetDir ] ++ concatMap (\x -> ["-js-lib-src",x]) jsSrcs } vanillaOptsNoJsLib = baseOpts `mappend` mempty { ghcOptMode = toFlag GhcModeMake, ghcOptNumJobs = numJobs,- ghcOptPackageKey = toFlag (pkgKey lbi),- ghcOptSigOf = hole_insts, ghcOptInputModules = toNubListR $ libModules lib, ghcOptHPCDir = hpcdir Hpc.Vanilla }@@ -507,7 +465,8 @@ ghcOptDynLinkMode = toFlag GhcDynamicOnly, ghcOptInputFiles = toNubListR dynamicObjectFiles, ghcOptOutputFile = toFlag sharedLibFilePath,- ghcOptPackageKey = toFlag (pkgKey lbi),+ ghcOptExtra = toNubListR $+ ghcjsSharedOptions libBi, ghcOptNoAutoLinkPackages = toFlag True, ghcOptPackageDBs = withPackageDB lbi, ghcOptPackages = toNubListR $@@ -531,16 +490,16 @@ runGhcjsProg ghcSharedLinkArgs -- | Start a REPL without loading any source files.-startInterpreter :: Verbosity -> ProgramConfiguration -> Compiler+startInterpreter :: Verbosity -> ProgramConfiguration -> Compiler -> Platform -> PackageDBStack -> IO ()-startInterpreter verbosity conf comp packageDBs = do+startInterpreter verbosity conf comp platform packageDBs = do let replOpts = mempty { ghcOptMode = toFlag GhcModeInteractive, ghcOptPackageDBs = packageDBs } checkPackageDbStack packageDBs (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram conf- runGHC verbosity ghcjsProg comp replOpts+ runGHC verbosity ghcjsProg comp platform replOpts buildExe, replExe :: Verbosity -> Cabal.Flag (Maybe Int) -> PackageDescription -> LocalBuildInfo@@ -556,8 +515,9 @@ (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi) let comp = compiler lbi+ platform = hostPlatform lbi implInfo = getImplInfo comp- runGhcjsProg = runGHC verbosity ghcjsProg comp+ runGhcjsProg = runGHC verbosity ghcjsProg comp platform exeBi = buildInfo exe -- exeNameReal, the name that GHC really uses (with .exe on Windows)@@ -728,9 +688,9 @@ whenProf $ copyModuleFiles "js_p_hi" whenShared $ copyModuleFiles "js_dyn_hi" - whenVanilla $ mapM_ (installOrdinary builtDir targetDir . toJSLibName) vanillaLibNames- whenProf $ mapM_ (installOrdinary builtDir targetDir . toJSLibName) profileLibNames- whenShared $ mapM_ (installShared builtDir dynlibTargetDir . toJSLibName) sharedLibNames+ whenVanilla $ installOrdinary builtDir targetDir $ toJSLibName vanillaLibName+ whenProf $ installOrdinary builtDir targetDir $ toJSLibName profileLibName+ whenShared $ installShared builtDir dynlibTargetDir $ toJSLibName sharedLibName when (ghcjsNativeToo $ compiler lbi) $ do -- copy .hi files over:@@ -739,35 +699,41 @@ whenShared $ copyModuleFiles "dyn_hi" -- copy the built library files over:- whenVanilla $ mapM_ (installOrdinary builtDir targetDir) vanillaLibNames- whenProf $ mapM_ (installOrdinary builtDir targetDir) profileLibNames- whenGHCi $ mapM_ (installOrdinary builtDir targetDir) ghciLibNames- whenShared $ mapM_ (installShared builtDir dynlibTargetDir) sharedLibNames+ whenVanilla $ installOrdinaryNative builtDir targetDir vanillaLibName+ whenProf $ installOrdinaryNative builtDir targetDir profileLibName+ whenGHCi $ installOrdinaryNative builtDir targetDir ghciLibName+ whenShared $ installSharedNative builtDir dynlibTargetDir sharedLibName where- install isShared srcDir dstDir name = do+ install isShared isJS srcDir dstDir name = do let src = srcDir </> name dst = dstDir </> name createDirectoryIfMissingVerbose verbosity True dstDir+ if isShared- then do when (stripLibs lbi) $ Strip.stripLib verbosity- (hostPlatform lbi) (withPrograms lbi) src- installExecutableFile verbosity src dst+ then installExecutableFile verbosity src dst else installOrdinaryFile verbosity src dst - installOrdinary = install False- installShared = install True+ when (stripLibs lbi && not isJS) $+ Strip.stripLib verbosity+ (hostPlatform lbi) (withPrograms lbi) dst + installOrdinary = install False True+ installShared = install True True++ installOrdinaryNative = install False False+ installSharedNative = install True False+ copyModuleFiles ext = findModuleFiles [builtDir] [ext] (libModules lib) >>= installOrdinaryFiles verbosity targetDir cid = compilerId (compiler lbi)- libNames = componentLibraries clbi- vanillaLibNames = map mkLibName libNames- profileLibNames = map mkProfLibName libNames- ghciLibNames = map Internal.mkGHCiLibName libNames- sharedLibNames = map (mkSharedLibName cid) libNames+ libName = componentUnitId clbi+ vanillaLibName = mkLibName libName+ profileLibName = mkProfLibName libName+ ghciLibName = Internal.mkGHCiLibName libName+ sharedLibName = (mkSharedLibName cid) libName hasLib = not $ null (libModules lib) && null (cSources (libBuildInfo lib))@@ -807,12 +773,12 @@ let libBi = libBuildInfo lib comp = compiler lbi+ platform = hostPlatform lbi vanillaArgs = (componentGhcOptions verbosity lbi libBi clbi (buildDir lbi)) `mappend` mempty { ghcOptMode = toFlag GhcModeAbiHash,- ghcOptPackageKey = toFlag (pkgKey lbi),- ghcOptInputModules = toNubListR $ exposedModules lib+ ghcOptInputModules = toNubListR $ PD.exposedModules lib } profArgs = adjustExts "js_p_hi" "js_p_o" vanillaArgs `mappend` mempty { ghcOptProfilingMode = toFlag True,@@ -823,7 +789,8 @@ else error "libAbiHash: Can't find an enabled library way" -- (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi)- getProgramInvocationOutput verbosity (ghcInvocation ghcjsProg comp ghcArgs)+ getProgramInvocationOutput verbosity+ (ghcInvocation ghcjsProg comp platform ghcArgs) adjustExts :: String -> String -> GhcOptions -> GhcOptions adjustExts hiSuf objSuf opts =@@ -833,16 +800,20 @@ } registerPackage :: Verbosity- -> InstalledPackageInfo- -> PackageDescription- -> LocalBuildInfo+ -> ProgramConfiguration -> Bool -> PackageDBStack+ -> InstalledPackageInfo -> IO ()-registerPackage verbosity installedPkgInfo _pkg lbi _inplace packageDbs =- HcPkg.reregister (hcPkgInfo $ withPrograms lbi) verbosity packageDbs- (Right installedPkgInfo)+registerPackage verbosity progdb multiInstance packageDbs installedPkgInfo+ | multiInstance+ = HcPkg.registerMultiInstance (hcPkgInfo progdb) verbosity+ packageDbs installedPkgInfo + | otherwise+ = HcPkg.reregister (hcPkgInfo progdb) verbosity+ packageDbs (Right installedPkgInfo)+ componentGhcOptions :: Verbosity -> LocalBuildInfo -> BuildInfo -> ComponentLocalBuildInfo -> FilePath -> GhcOptions@@ -882,7 +853,10 @@ , HcPkg.noPkgDbStack = False , HcPkg.noVerboseFlag = False , HcPkg.flagPackageConf = False- , HcPkg.useSingleFileDb = v < [7,9]+ , HcPkg.supportsDirDbs = True+ , HcPkg.requiresDirDbs = v >= [7,10]+ , HcPkg.nativeMultiInstance = v >= [7,10]+ , HcPkg.recacheMultiInstance = True } where v = versionBranch ver
Distribution/Simple/Haddock.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE DeriveGeneric #-}+ ----------------------------------------------------------------------------- -- | -- Module : Distribution.Simple.Haddock@@ -24,61 +26,27 @@ import qualified Distribution.Simple.GHCJS as GHCJS -- local+import Distribution.Compat.Semigroup as Semi import Distribution.Package- ( PackageIdentifier(..)- , Package(..)- , PackageName(..), packageName ) import qualified Distribution.ModuleName as ModuleName-import Distribution.PackageDescription as PD- ( PackageDescription(..), BuildInfo(..), usedExtensions- , hcSharedOptions- , Library(..), hasLibs, Executable(..)- , TestSuite(..), TestSuiteInterface(..)- , Benchmark(..), BenchmarkInterface(..) )-import Distribution.Simple.Compiler- ( Compiler, compilerInfo, CompilerFlavor(..)- , compilerFlavor, compilerCompatVersion )+import Distribution.PackageDescription as PD hiding (Flag)+import Distribution.Simple.Compiler hiding (Flag) import Distribution.Simple.Program.GHC- ( GhcOptions(..), GhcDynLinkMode(..), renderGhcOptions ) import Distribution.Simple.Program- ( ConfiguredProgram(..), lookupProgramVersion, requireProgramVersion- , rawSystemProgram, rawSystemProgramStdout- , hscolourProgram, haddockProgram ) import Distribution.Simple.PreProcess- ( PPSuffixHandler, preprocessComponent) import Distribution.Simple.Setup- ( defaultHscolourFlags- , Flag(..), toFlag, flagToMaybe, flagToList, fromFlag- , HaddockFlags(..), HscolourFlags(..) )-import Distribution.Simple.Build (initialBuildSteps)+import Distribution.Simple.Build import Distribution.Simple.InstallDirs- ( InstallDirs(..)- , PathTemplateEnv, PathTemplate, PathTemplateVariable(..)- , toPathTemplate, fromPathTemplate- , substPathTemplate, initialPathTemplateEnv )-import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), Component(..), ComponentLocalBuildInfo(..)- , withAllComponentsInBuildOrder )+import Distribution.Simple.LocalBuildInfo hiding (substPathTemplate) import Distribution.Simple.BuildPaths- ( haddockName, hscolourPref, autogenModulesDir)-import Distribution.Simple.PackageIndex (dependencyClosure) import qualified Distribution.Simple.PackageIndex as PackageIndex import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo- ( InstalledPackageInfo_(..) )-import Distribution.InstalledPackageInfo- ( InstalledPackageInfo )+import Distribution.InstalledPackageInfo ( InstalledPackageInfo ) import Distribution.Simple.Utils- ( die, copyFileTo, warn, notice, intercalate, setupMessage- , createDirectoryIfMissingVerbose- , TempFileOptions(..), defaultTempFileOptions- , withTempFileEx, copyFileVerbose- , withTempDirectoryEx, matchFileGlob- , findFileWithExtension, findFile )+import Distribution.System import Distribution.Text- ( display, simpleParse ) import Distribution.Utils.NubList- ( toNubListR )-+import Distribution.Version import Distribution.Verbosity import Language.Haskell.Extension @@ -86,15 +54,14 @@ import Control.Monad ( when, forM_ ) import Data.Char ( isSpace ) import Data.Either ( rights )-import Data.Monoid-import Data.Foldable ( foldl' )+import Data.Foldable ( traverse_, foldl' ) import Data.Maybe ( fromMaybe, listToMaybe )+import GHC.Generics ( Generic ) import System.Directory (doesFileExist) import System.FilePath ( (</>), (<.>) , normalise, splitPath, joinPath, isAbsolute ) import System.IO (hClose, hPutStr, hPutStrLn, hSetEncoding, utf8)-import Distribution.Version -- ------------------------------------------------------------------------------ -- Types@@ -133,7 +100,7 @@ -- ^ To find the correct GHC, required. argTargets :: [FilePath] -- ^ Modules to process.-}+} deriving Generic -- | The FilePath of a directory, it's a monoid under '(</>)'. newtype Directory = Dir { unDir' :: FilePath } deriving (Read,Show,Eq,Ord)@@ -163,7 +130,28 @@ ++ "a library. Perhaps you want to use the --executables, --tests or" ++ " --benchmarks flags." -haddock pkg_descr lbi suffixes flags = do+haddock pkg_descr lbi suffixes flags' = do+ let verbosity = flag haddockVerbosity+ comp = compiler lbi+ platform = hostPlatform lbi++ flags+ | fromFlag (haddockForHackage flags') = flags'+ { haddockHoogle = Flag True+ , haddockHtml = Flag True+ , haddockHtmlLocation = Flag (pkg_url ++ "/docs")+ , haddockContents = Flag (toPathTemplate pkg_url)+ , haddockHscolour = Flag True+ }+ | otherwise = flags'+ pkg_url = "/package/$pkg-$version"+ flag f = fromFlag $ f flags++ tmpFileOpts = defaultTempFileOptions+ { optKeepTempFiles = flag haddockKeepTempFiles }+ htmlTemplate = fmap toPathTemplate . flagToMaybe . haddockHtmlLocation+ $ flags+ setupMessage verbosity "Running Haddock for" (packageId pkg_descr) (confHaddock, version, _) <- requireProgramVersion verbosity haddockProgram@@ -199,7 +187,8 @@ let commonArgs = mconcat [ libdirArgs , fromFlags (haddockTemplateEnv lbi (packageId pkg_descr)) flags- , fromPackageDescription pkg_descr ]+ , fromPackageDescription forDist pkg_descr ]+ forDist = fromFlagOrDefault False (haddockForHackage flags) let pre c = preprocessComponent pkg_descr c lbi False verbosity suffixes withAllComponentsInBuildOrder pkg_descr lbi $ \component clbi -> do@@ -212,7 +201,8 @@ exeArgs <- fromExecutable verbosity tmp lbi exe clbi htmlTemplate version let exeArgs' = commonArgs `mappend` exeArgs- runHaddock verbosity tmpFileOpts comp confHaddock exeArgs'+ runHaddock verbosity tmpFileOpts comp platform+ confHaddock exeArgs' Nothing -> do warn (fromFlag $ haddockVerbosity flags) "Unsupported component, skipping..."@@ -224,7 +214,7 @@ libArgs <- fromLibrary verbosity tmp lbi lib clbi htmlTemplate version let libArgs' = commonArgs `mappend` libArgs- runHaddock verbosity tmpFileOpts comp confHaddock libArgs'+ runHaddock verbosity tmpFileOpts comp platform confHaddock libArgs' CExe _ -> when (flag haddockExecutables) $ doExe component CTest _ -> when (flag haddockTestSuites) $ doExe component CBench _ -> when (flag haddockBenchmarks) $ doExe component@@ -232,14 +222,6 @@ forM_ (extraDocFiles pkg_descr) $ \ fpath -> do files <- matchFileGlob fpath forM_ files $ copyFileTo verbosity (unDir $ argOutputDir commonArgs)- where- verbosity = flag haddockVerbosity- keepTempFiles = flag haddockKeepTempFiles- comp = compiler lbi- tmpFileOpts = defaultTempFileOptions { optKeepTempFiles = keepTempFiles }- flag f = fromFlag $ f flags- htmlTemplate = fmap toPathTemplate . flagToMaybe . haddockHtmlLocation- $ flags -- ------------------------------------------------------------------------------ -- Contributions to HaddockArgs.@@ -267,12 +249,11 @@ argOutputDir = maybe mempty Dir . flagToMaybe $ haddockDistPref flags } -fromPackageDescription :: PackageDescription -> HaddockArgs-fromPackageDescription pkg_descr =+fromPackageDescription :: Bool -> PackageDescription -> HaddockArgs+fromPackageDescription forDist pkg_descr = mempty { argInterfaceFile = Flag $ haddockName pkg_descr, argPackageName = Flag $ packageId $ pkg_descr,- argOutputDir = Dir $ "doc" </> "html"- </> display (packageName pkg_descr),+ argOutputDir = Dir $ "doc" </> "html" </> name, argPrologue = Flag $ if null desc then synopsis pkg_descr else desc, argTitle = Flag $ showPkg ++ subtitle@@ -280,6 +261,9 @@ where desc = PD.description pkg_descr showPkg = display (packageId pkg_descr)+ name+ | forDist = showPkg ++ "-docs"+ | otherwise = display (packageName pkg_descr) subtitle | null (synopsis pkg_descr) = "" | otherwise = ": " ++ synopsis pkg_descr @@ -311,8 +295,7 @@ -- haddock to write them elsewhere. ghcOptObjDir = toFlag tmp, ghcOptHiDir = toFlag tmp,- ghcOptStubDir = toFlag tmp,- ghcOptPackageKey = toFlag $ pkgKey lbi+ ghcOptStubDir = toFlag tmp } `mappend` getGhcCppOpts haddockVersion bi sharedOpts = vanillaOpts { ghcOptDynLinkMode = toFlag GhcDynamicOnly,@@ -411,7 +394,7 @@ -> IO HaddockArgs getInterfaces verbosity lbi clbi htmlTemplate = do (packageFlags, warnings) <- haddockPackageFlags lbi clbi htmlTemplate- maybe (return ()) (warn verbosity) warnings+ traverse_ (warn verbosity) warnings return $ mempty { argInterfaces = packageFlags }@@ -446,13 +429,14 @@ runHaddock :: Verbosity -> TempFileOptions -> Compiler+ -> Platform -> ConfiguredProgram -> HaddockArgs -> IO ()-runHaddock verbosity tmpFileOpts comp confHaddock args = do+runHaddock verbosity tmpFileOpts comp platform confHaddock args = do let haddockVersion = fromMaybe (error "unable to determine haddock version") (programVersion confHaddock)- renderArgs verbosity tmpFileOpts haddockVersion comp args $+ renderArgs verbosity tmpFileOpts haddockVersion comp platform args $ \(flags,result)-> do rawSystemProgram verbosity confHaddock flags@@ -464,10 +448,11 @@ -> TempFileOptions -> Version -> Compiler+ -> Platform -> HaddockArgs -> (([String], FilePath) -> IO a) -> IO a-renderArgs verbosity tmpFileOpts version comp args k = do+renderArgs verbosity tmpFileOpts version comp platform args k = do let haddockSupportsUTF8 = version >= Version [2,14,4] [] haddockSupportsResponseFiles = version > Version [2,16,2] [] createDirectoryIfMissingVerbose verbosity True outputDir@@ -478,8 +463,8 @@ hPutStrLn h $ fromFlag $ argPrologue args hClose h let pflag = "--prologue=" ++ prologueFileName- renderedArgs = pflag : renderPureArgs version comp args- if haddockSupportsResponseFiles + renderedArgs = pflag : renderPureArgs version comp platform args+ if haddockSupportsResponseFiles then withTempFileEx tmpFileOpts outputDir "haddock-response.txt" $ \responseFileName hf -> do@@ -516,8 +501,8 @@ | otherwise = c:cs escapeArg = reverse . foldl' escape [] -renderPureArgs :: Version -> Compiler -> HaddockArgs -> [String]-renderPureArgs version comp args = concat+renderPureArgs :: Version -> Compiler -> Platform -> HaddockArgs -> [String]+renderPureArgs version comp platform args = concat [ (:[]) . (\f -> "--dump-interface="++ unDir (argOutputDir args) </> f) . fromFlag . argInterfaceFile $ args @@ -559,7 +544,7 @@ . fromFlag . argTitle $ args , [ "--optghc=" ++ opt | (opts, _ghcVer) <- flagToList (argGhcOptions args)- , opt <- renderGhcOptions comp opts ]+ , opt <- renderGhcOptions comp platform opts ] , maybe [] (\l -> ["-B"++l]) $ flagToMaybe (argGhcLibDir args) -- error if Nothing?@@ -631,7 +616,7 @@ haddockPackageFlags lbi clbi htmlTemplate = do let allPkgs = installedPkgs lbi directDeps = map fst (componentPackageDeps clbi)- transitiveDeps <- case dependencyClosure allPkgs directDeps of+ transitiveDeps <- case PackageIndex.dependencyClosure allPkgs directDeps of Left x -> return x Right inf -> die $ "internal error when calculating transitive " ++ "package dependencies.\nDebug info: " ++ show inf@@ -646,7 +631,9 @@ haddockTemplateEnv :: LocalBuildInfo -> PackageIdentifier -> PathTemplateEnv haddockTemplateEnv lbi pkg_id = (PrefixVar, prefix (installDirTemplates lbi))- : initialPathTemplateEnv pkg_id (pkgKey lbi) (compilerInfo (compiler lbi))+ -- We want the legacy unit ID here, because it gives us nice paths+ -- (Haddock people don't care about the dependencies)+ : initialPathTemplateEnv pkg_id (mkLegacyUnitId pkg_id) (compilerInfo (compiler lbi)) (hostPlatform lbi) -- ------------------------------------------------------------------------------@@ -776,44 +763,15 @@ -- ------------------------------------------------------------------------------ -- Boilerplate Monoid instance. instance Monoid HaddockArgs where- mempty = HaddockArgs {- argInterfaceFile = mempty,- argPackageName = mempty,- argHideModules = mempty,- argIgnoreExports = mempty,- argLinkSource = mempty,- argCssFile = mempty,- argContents = mempty,- argVerbose = mempty,- argOutput = mempty,- argInterfaces = mempty,- argOutputDir = mempty,- argTitle = mempty,- argPrologue = mempty,- argGhcOptions = mempty,- argGhcLibDir = mempty,- argTargets = mempty- }- mappend a b = HaddockArgs {- argInterfaceFile = mult argInterfaceFile,- argPackageName = mult argPackageName,- argHideModules = mult argHideModules,- argIgnoreExports = mult argIgnoreExports,- argLinkSource = mult argLinkSource,- argCssFile = mult argCssFile,- argContents = mult argContents,- argVerbose = mult argVerbose,- argOutput = mult argOutput,- argInterfaces = mult argInterfaces,- argOutputDir = mult argOutputDir,- argTitle = mult argTitle,- argPrologue = mult argPrologue,- argGhcOptions = mult argGhcOptions,- argGhcLibDir = mult argGhcLibDir,- argTargets = mult argTargets- }- where mult f = f a `mappend` f b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup HaddockArgs where+ (<>) = gmappend+ instance Monoid Directory where mempty = Dir "."- mappend (Dir m) (Dir n) = Dir $ m </> n+ mappend = (Semi.<>)++instance Semigroup Directory where+ Dir m <> Dir n = Dir $ m </> n
Distribution/Simple/HaskellSuite.hs view
@@ -1,10 +1,6 @@-{-# LANGUAGE CPP #-} module Distribution.Simple.HaskellSuite where import Control.Monad-#if __GLASGOW_HASKELL__ < 710-import Control.Applicative-#endif import Data.Maybe import Data.Version import qualified Data.Map as M (empty)@@ -24,7 +20,6 @@ import Distribution.Compat.Exception import Language.Haskell.Extension import Distribution.Simple.Program.Builtin- (haskellSuiteProgram, haskellSuitePkgProgram) configure :: Verbosity -> Maybe FilePath -> Maybe FilePath@@ -60,7 +55,7 @@ let haskellSuiteProgram' = haskellSuiteProgram- { programFindLocation = \v _p -> findProgramLocation v hcPath }+ { programFindLocation = \v p -> findProgramOnSearchPath v p hcPath } -- NB: cannot call requireProgram right away — it'd think that -- the program is already configured and won't reconfigure it again.@@ -106,7 +101,7 @@ getExtensions :: Verbosity -> ConfiguredProgram -> IO [(Extension, Compiler.Flag)] getExtensions verbosity prog = do extStrs <-- lines <$>+ lines `fmap` rawSystemStdout verbosity (programPath prog) ["--supported-extensions"] return [ (ext, "-X" ++ display ext) | Just ext <- map simpleParse extStrs ]@@ -114,7 +109,7 @@ getLanguages :: Verbosity -> ConfiguredProgram -> IO [(Language, Compiler.Flag)] getLanguages verbosity prog = do langStrs <-- lines <$>+ lines `fmap` rawSystemStdout verbosity (programPath prog) ["--supported-languages"] return [ (ext, "-G" ++ display ext) | Just ext <- map simpleParse langStrs ]@@ -190,8 +185,9 @@ -> FilePath -- ^Build location -> PackageDescription -> Library+ -> ComponentLocalBuildInfo -> IO ()-installLib verbosity lbi targetDir dynlibTargetDir builtDir pkg lib = do+installLib verbosity lbi targetDir dynlibTargetDir builtDir pkg lib _clbi = do let conf = withPrograms lbi runDbProgram verbosity haskellSuitePkgProgram conf $ [ "install-library"@@ -203,14 +199,12 @@ registerPackage :: Verbosity- -> InstalledPackageInfo- -> PackageDescription- -> LocalBuildInfo- -> Bool+ -> ProgramConfiguration -> PackageDBStack+ -> InstalledPackageInfo -> IO ()-registerPackage verbosity installedPkgInfo _pkg lbi _inplace packageDbs = do- (hspkg, _) <- requireProgram verbosity haskellSuitePkgProgram (withPrograms lbi)+registerPackage verbosity progdb packageDbs installedPkgInfo = do+ (hspkg, _) <- requireProgram verbosity haskellSuitePkgProgram progdb runProgramInvocation verbosity $ (programInvocation hspkg
Distribution/Simple/Install.hs view
@@ -16,13 +16,9 @@ install, ) where -import Distribution.PackageDescription (- PackageDescription(..), BuildInfo(..), Library(..),- hasLibs, withLib, hasExes, withExe )+import Distribution.PackageDescription import Distribution.Package (Package(..))-import Distribution.Simple.LocalBuildInfo (- LocalBuildInfo(..), InstallDirs(..), absoluteInstallDirs,- substPathTemplate, withLibLBI)+import Distribution.Simple.LocalBuildInfo import Distribution.Simple.BuildPaths (haddockName, haddockPref) import Distribution.Simple.Utils ( createDirectoryIfMissingVerbose@@ -69,6 +65,8 @@ htmldir = htmlPref, haddockdir = interfacePref, includedir = incPref})+ -- Using the library clbi for binPref is a hack;+ -- binPref should be computed per executable = absoluteInstallDirs pkg_descr lbi copydest --TODO: decide if we need the user to be able to control the libdir@@ -79,6 +77,8 @@ progPrefixPref = substPathTemplate (packageId pkg_descr) lbi (progPrefix lbi) progSuffixPref = substPathTemplate (packageId pkg_descr) lbi (progSuffix lbi) + unless (hasLibs pkg_descr || hasExes pkg_descr) $+ die "No executables and no library found. Nothing to do." docExists <- doesDirectoryExist $ haddockPref distPref pkg_descr info verbosity ("directory " ++ haddockPref distPref pkg_descr ++ " does exist: " ++ show docExists)@@ -124,32 +124,33 @@ -- install include files for all compilers - they may be needed to compile -- haskell files (using the CPP extension)+ -- when (hasLibs pkg_descr) $ installIncludeFiles verbosity pkg_descr incPref - case compilerFlavor (compiler lbi) of- GHC -> do withLibLBI pkg_descr lbi $- GHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr- withExe pkg_descr $- GHC.installExe verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr- GHCJS-> do withLibLBI pkg_descr lbi $- GHCJS.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr- withExe pkg_descr $- GHCJS.installExe verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr- LHC -> do withLibLBI pkg_descr lbi $- LHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr- withExe pkg_descr $- LHC.installExe verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr- JHC -> do withLib pkg_descr $- JHC.installLib verbosity libPref buildPref pkg_descr- withExe pkg_descr $- JHC.installExe verbosity binPref buildPref (progPrefixPref, progSuffixPref) pkg_descr- UHC -> do withLib pkg_descr $ UHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr- HaskellSuite {} ->- withLib pkg_descr $- HaskellSuite.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr- _ -> die $ "installing with "- ++ display (compilerFlavor (compiler lbi))- ++ " is not implemented"+ withLibLBI pkg_descr lbi $+ case compilerFlavor (compiler lbi) of+ GHC -> GHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr+ GHCJS -> GHCJS.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr+ LHC -> LHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr+ JHC -> JHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr+ UHC -> UHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr+ HaskellSuite _ -> HaskellSuite.installLib+ verbosity lbi libPref dynlibPref buildPref pkg_descr+ _ -> \_ _ -> die $ "installing with "+ ++ display (compilerFlavor (compiler lbi))+ ++ " is not implemented"++ withExe pkg_descr $+ case compilerFlavor (compiler lbi) of+ GHC -> GHC.installExe verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr+ GHCJS -> GHCJS.installExe verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr+ LHC -> LHC.installExe verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr+ JHC -> JHC.installExe verbosity binPref buildPref (progPrefixPref, progSuffixPref) pkg_descr+ UHC -> \_ -> return ()+ HaskellSuite {} -> \_ -> return ()+ _ -> \_ -> die $ "installing with "+ ++ display (compilerFlavor (compiler lbi))+ ++ " is not implemented" -- register step should be performed by caller. -- | Install the files listed in data-files
Distribution/Simple/InstallDirs.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE CPP, ForeignFunctionInterface #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-} -----------------------------------------------------------------------------@@ -45,25 +47,19 @@ import Distribution.Compat.Binary (Binary)+import Distribution.Compat.Semigroup as Semi+import Distribution.Package+import Distribution.System+import Distribution.Compiler+import Distribution.Text+ import Data.List (isPrefixOf) import Data.Maybe (fromMaybe)-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid (Monoid(..))-#endif import GHC.Generics (Generic) import System.Directory (getAppUserDataDirectory) import System.FilePath ((</>), isPathSeparator, pathSeparator) import System.FilePath (dropDrive) -import Distribution.Package- ( PackageIdentifier, PackageKey, packageName, packageVersion, packageKeyLibraryName )-import Distribution.System- ( OS(..), buildOS, Platform(..) )-import Distribution.Compiler- ( AbiTag(..), abiTagString, CompilerInfo(..), CompilerFlavor(..) )-import Distribution.Text- ( display )- #if mingw32_HOST_OS import Foreign import Foreign.C@@ -95,46 +91,16 @@ htmldir :: dir, haddockdir :: dir, sysconfdir :: dir- } deriving (Generic, Read, Show)+ } deriving (Eq, Read, Show, Functor, Generic) instance Binary dir => Binary (InstallDirs dir) -instance Functor InstallDirs where- fmap f dirs = InstallDirs {- prefix = f (prefix dirs),- bindir = f (bindir dirs),- libdir = f (libdir dirs),- libsubdir = f (libsubdir dirs),- dynlibdir = f (dynlibdir dirs),- libexecdir = f (libexecdir dirs),- includedir = f (includedir dirs),- datadir = f (datadir dirs),- datasubdir = f (datasubdir dirs),- docdir = f (docdir dirs),- mandir = f (mandir dirs),- htmldir = f (htmldir dirs),- haddockdir = f (haddockdir dirs),- sysconfdir = f (sysconfdir dirs)- }+instance (Semigroup dir, Monoid dir) => Monoid (InstallDirs dir) where+ mempty = gmempty+ mappend = (Semi.<>) -instance Monoid dir => Monoid (InstallDirs dir) where- mempty = InstallDirs {- prefix = mempty,- bindir = mempty,- libdir = mempty,- libsubdir = mempty,- dynlibdir = mempty,- libexecdir = mempty,- includedir = mempty,- datadir = mempty,- datasubdir = mempty,- docdir = mempty,- mandir = mempty,- htmldir = mempty,- haddockdir = mempty,- sysconfdir = mempty- }- mappend = combineInstallDirs mappend+instance Semigroup dir => Semigroup (InstallDirs dir) where+ (<>) = gmappend combineInstallDirs :: (a -> b -> c) -> InstallDirs a@@ -286,13 +252,13 @@ -- substituting for all the variables in the abstract paths, to get real -- absolute path. absoluteInstallDirs :: PackageIdentifier- -> PackageKey+ -> UnitId -> CompilerInfo -> CopyDest -> Platform -> InstallDirs PathTemplate -> InstallDirs FilePath-absoluteInstallDirs pkgId pkg_key compilerId copydest platform dirs =+absoluteInstallDirs pkgId libname compilerId copydest platform dirs = (case copydest of CopyTo destdir -> fmap ((destdir </>) . dropDrive) _ -> id)@@ -300,7 +266,7 @@ . fmap fromPathTemplate $ substituteInstallDirTemplates env dirs where- env = initialPathTemplateEnv pkgId pkg_key compilerId platform+ env = initialPathTemplateEnv pkgId libname compilerId platform -- |The location prefix for the /copy/ command.@@ -316,12 +282,12 @@ -- independent\" package). -- prefixRelativeInstallDirs :: PackageIdentifier- -> PackageKey+ -> UnitId -> CompilerInfo -> Platform -> InstallDirTemplates -> InstallDirs (Maybe FilePath)-prefixRelativeInstallDirs pkgId pkg_key compilerId platform dirs =+prefixRelativeInstallDirs pkgId libname compilerId platform dirs = fmap relative . appendSubdirs combinePathTemplate $ -- substitute the path template into each other, except that we map@@ -331,7 +297,7 @@ prefix = PathTemplate [Variable PrefixVar] } where- env = initialPathTemplateEnv pkgId pkg_key compilerId platform+ env = initialPathTemplateEnv pkgId libname compilerId platform -- If it starts with $prefix then it's relative and produce the relative -- path by stripping off $prefix/ or $prefix@@ -348,7 +314,8 @@ -- | An abstract path, possibly containing variables that need to be -- substituted for to get a real 'FilePath'. ---newtype PathTemplate = PathTemplate [PathComponent] deriving (Eq, Generic, Ord)+newtype PathTemplate = PathTemplate [PathComponent]+ deriving (Eq, Ord, Generic) instance Binary PathTemplate @@ -371,8 +338,7 @@ | PkgNameVar -- ^ The @$pkg@ package name path variable | PkgVerVar -- ^ The @$version@ package version path variable | PkgIdVar -- ^ The @$pkgid@ package Id path variable, eg @foo-1.0@- | PkgKeyVar -- ^ The @$pkgkey@ package key path variable- | LibNameVar -- ^ The @$libname@ expanded package key path variable+ | LibNameVar -- ^ The @$libname@ path variable | CompilerVar -- ^ The compiler name and version, eg @ghc-6.6.1@ | OSVar -- ^ The operating system name, eg @windows@ or @linux@ | ArchVar -- ^ The CPU architecture name, eg @i386@ or @x86_64@@@ -415,22 +381,21 @@ -- | The initial environment has all the static stuff but no paths initialPathTemplateEnv :: PackageIdentifier- -> PackageKey+ -> UnitId -> CompilerInfo -> Platform -> PathTemplateEnv-initialPathTemplateEnv pkgId pkg_key compiler platform =- packageTemplateEnv pkgId pkg_key+initialPathTemplateEnv pkgId libname compiler platform =+ packageTemplateEnv pkgId libname ++ compilerTemplateEnv compiler ++ platformTemplateEnv platform ++ abiTemplateEnv compiler platform -packageTemplateEnv :: PackageIdentifier -> PackageKey -> PathTemplateEnv-packageTemplateEnv pkgId pkg_key =+packageTemplateEnv :: PackageIdentifier -> UnitId -> PathTemplateEnv+packageTemplateEnv pkgId libname = [(PkgNameVar, PathTemplate [Ordinary $ display (packageName pkgId)]) ,(PkgVerVar, PathTemplate [Ordinary $ display (packageVersion pkgId)])- ,(PkgKeyVar, PathTemplate [Ordinary $ display pkg_key])- ,(LibNameVar, PathTemplate [Ordinary $ packageKeyLibraryName pkgId pkg_key])+ ,(LibNameVar, PathTemplate [Ordinary $ display libname]) ,(PkgIdVar, PathTemplate [Ordinary $ display pkgId]) ] @@ -479,8 +444,7 @@ instance Show PathTemplateVariable where show PrefixVar = "prefix"- show PkgKeyVar = "pkgkey"- show LibNameVar = "libname"+ show LibNameVar = "libname" show BindirVar = "bindir" show LibdirVar = "libdir" show LibsubdirVar = "libsubdir"@@ -517,8 +481,8 @@ ,("docdir", DocdirVar) ,("htmldir", HtmldirVar) ,("pkgid", PkgIdVar)- ,("pkgkey", PkgKeyVar) ,("libname", LibNameVar)+ ,("pkgkey", LibNameVar) -- backwards compatibility ,("pkg", PkgNameVar) ,("version", PkgVerVar) ,("compiler", CompilerVar)
Distribution/Simple/JHC.hs view
@@ -16,40 +16,23 @@ installLib, installExe ) where -import Distribution.PackageDescription as PD- ( PackageDescription(..), BuildInfo(..), Executable(..)- , Library(..), libModules, hcOptions, usedExtensions )+import Distribution.PackageDescription as PD hiding (Flag) import Distribution.InstalledPackageInfo- ( emptyInstalledPackageInfo, ) import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo import Distribution.Simple.PackageIndex (InstalledPackageIndex) import qualified Distribution.Simple.PackageIndex as PackageIndex import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), ComponentLocalBuildInfo(..) ) import Distribution.Simple.BuildPaths- ( autogenModulesDir, exeExtension ) import Distribution.Simple.Compiler- ( CompilerFlavor(..), CompilerId(..), Compiler(..), AbiTag(..)- , PackageDBStack, Flag, languageToFlags, extensionsToFlags ) import Language.Haskell.Extension- ( Language(Haskell98), Extension(..), KnownExtension(..)) import Distribution.Simple.Program- ( ConfiguredProgram(..), jhcProgram, ProgramConfiguration- , userMaybeSpecifyPath, requireProgramVersion, lookupProgram- , rawSystemProgram, rawSystemProgramStdoutConf ) import Distribution.Version- ( Version(..), orLaterVersion ) import Distribution.Package- ( Package(..), InstalledPackageId(InstalledPackageId),- pkgName, pkgVersion, ) import Distribution.Simple.Utils- ( createDirectoryIfMissingVerbose, writeFileAtomic- , installOrdinaryFile, installExecutableFile- , intercalate )-import System.FilePath ( (</>) ) import Distribution.Verbosity import Distribution.Text- ( Text(parse), display )++import System.FilePath ( (</>) ) import Distribution.Compat.ReadP ( readP_to_S, string, skipSpaces ) import Distribution.System ( Platform )@@ -116,8 +99,7 @@ return $ PackageIndex.fromList $ map (\p -> emptyInstalledPackageInfo {- InstalledPackageInfo.installedPackageId =- InstalledPackageId (display p),+ InstalledPackageInfo.installedUnitId = mkLegacyUnitId p, InstalledPackageInfo.sourcePackageId = p }) $ concatMap parseLine $@@ -181,8 +163,16 @@ ,sline "hidden-modules" (comma . otherModules . libBuildInfo . lib) ] -installLib :: Verbosity -> FilePath -> FilePath -> PackageDescription -> Library -> IO ()-installLib verb dest build_dir pkg_descr _ = do+installLib :: Verbosity+ -> LocalBuildInfo+ -> FilePath+ -> FilePath+ -> FilePath+ -> PackageDescription+ -> Library+ -> ComponentLocalBuildInfo+ -> IO ()+installLib verb _lbi dest _dyn_dest build_dir pkg_descr _lib _clbi = do let p = display (packageId pkg_descr)++".hl" createDirectoryIfMissingVerbose verb True dest installOrdinaryFile verb (build_dir </> p) (dest </> p)
Distribution/Simple/LHC.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Simple.LHC@@ -41,67 +40,37 @@ ghcVerbosityOptions ) where -import Distribution.PackageDescription as PD- ( PackageDescription(..), BuildInfo(..), Executable(..)- , Library(..), libModules, hcOptions, hcProfOptions, hcSharedOptions- , usedExtensions, allExtensions )+import Distribution.PackageDescription as PD hiding (Flag) import Distribution.InstalledPackageInfo- ( InstalledPackageInfo- , parseInstalledPackageInfo ) import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo- ( InstalledPackageInfo_(..) ) import Distribution.Simple.PackageIndex import qualified Distribution.Simple.PackageIndex as PackageIndex-import Distribution.ParseUtils ( ParseResult(..) ) import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), ComponentLocalBuildInfo(..),- LibraryName(..) )-import Distribution.Simple.InstallDirs import Distribution.Simple.BuildPaths import Distribution.Simple.Utils import Distribution.Package- ( Package(..) ) import qualified Distribution.ModuleName as ModuleName import Distribution.Simple.Program- ( Program(..), ConfiguredProgram(..), ProgramConfiguration- , ProgramSearchPath, ProgramLocation(..)- , rawSystemProgram, rawSystemProgramConf- , rawSystemProgramStdout, rawSystemProgramStdoutConf- , requireProgramVersion- , userMaybeSpecifyPath, programPath, lookupProgram, addKnownProgram- , arProgram, ldProgram- , gccProgram, stripProgram- , lhcProgram, lhcPkgProgram ) import qualified Distribution.Simple.Program.HcPkg as HcPkg import Distribution.Simple.Compiler- ( CompilerFlavor(..), CompilerId(..), Compiler(..), compilerVersion- , OptimisationLevel(..), PackageDB(..), PackageDBStack, AbiTag(..)- , Flag, languageToFlags, extensionsToFlags ) import Distribution.Version- ( Version(..), orLaterVersion )-import Distribution.System- ( OS(..), buildOS ) import Distribution.Verbosity import Distribution.Text- ( display, simpleParse )+import Distribution.Compat.Exception+import Distribution.System import Language.Haskell.Extension- ( Language(Haskell98), Extension(..), KnownExtension(..) ) import Control.Monad ( unless, when )+import Data.Monoid as Mon import Data.List import qualified Data.Map as M ( empty ) import Data.Maybe ( catMaybes )-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid ( Monoid(..) )-#endif import System.Directory ( removeFile, renameFile, getDirectoryContents, doesFileExist, getTemporaryDirectory ) import System.FilePath ( (</>), (<.>), takeExtension, takeDirectory, replaceExtension ) import System.IO (hClose, hPutStrLn)-import Distribution.Compat.Exception (catchExit, catchIO)-import Distribution.System ( Platform ) -- ----------------------------------------------------------------------------- -- Configuring@@ -162,10 +131,11 @@ -- on Windows finding and configuring ghc's gcc and ld is a bit special findProg :: Program -> FilePath- -> Verbosity -> ProgramSearchPath -> IO (Maybe FilePath)+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath])) findProg prog location | isWindows = \verbosity searchpath -> do exists <- doesFileExist location- if exists then return (Just location)+ if exists then return (Just (location, [])) else do warn verbosity ("Couldn't find " ++ programName prog ++ " where I expected it. Trying the search path.") programFindLocation prog verbosity searchpath | otherwise = programFindLocation prog@@ -231,7 +201,7 @@ pkgss <- getInstalledPackages' lhcPkg verbosity packagedbs conf let indexes = [ PackageIndex.fromList (map (substTopDir topDir) pkgs) | (_, pkgs) <- pkgss ]- return $! (mconcat indexes)+ return $! (Mon.mconcat indexes) where -- On Windows, various fields have $topdir/foo rather than full@@ -319,12 +289,8 @@ buildLib :: Verbosity -> PackageDescription -> LocalBuildInfo -> Library -> ComponentLocalBuildInfo -> IO () buildLib verbosity pkg_descr lbi lib clbi = do- libName <- case componentLibraries clbi of- [libName] -> return libName- [] -> die "No library name found when building library"- _ -> die "Multiple library names found when building library"-- let pref = buildDir lbi+ let libName = componentUnitId clbi+ pref = buildDir lbi pkgid = packageId pkg_descr runGhcProg = rawSystemProgramConf verbosity lhcProgram (withPrograms lbi) ifVanillaLib forceVanilla = when (forceVanilla || withVanillaLib lbi)@@ -687,8 +653,8 @@ _ -> ["-optc-O2"]) ++ ["-odir", odir] -mkGHCiLibName :: LibraryName -> String-mkGHCiLibName (LibraryName lib) = lib <.> "o"+mkGHCiLibName :: UnitId -> String+mkGHCiLibName lib = getHSLibraryName lib <.> "o" -- ----------------------------------------------------------------------------- -- Installing@@ -755,18 +721,18 @@ flip mapM_ hcrFiles $ \(srcBase, srcFile) -> runLhc ["--install-library", srcBase </> srcFile] -- copy the built library files over:- ifVanilla $ mapM_ (copy builtDir targetDir) vanillaLibNames- ifProf $ mapM_ (copy builtDir targetDir) profileLibNames- ifGHCi $ mapM_ (copy builtDir targetDir) ghciLibNames- ifShared $ mapM_ (copy builtDir dynlibTargetDir) sharedLibNames+ ifVanilla $ copy builtDir targetDir vanillaLibName+ ifProf $ copy builtDir targetDir profileLibName+ ifGHCi $ copy builtDir targetDir ghciLibName+ ifShared $ copy builtDir dynlibTargetDir sharedLibName where cid = compilerId (compiler lbi)- libNames = componentLibraries clbi- vanillaLibNames = map mkLibName libNames- profileLibNames = map mkProfLibName libNames- ghciLibNames = map mkGHCiLibName libNames- sharedLibNames = map (mkSharedLibName cid) libNames+ libName = componentUnitId clbi+ vanillaLibName = mkLibName libName+ profileLibName = mkProfLibName libName+ ghciLibName = mkGHCiLibName libName+ sharedLibName = mkSharedLibName cid libName hasLib = not $ null (libModules lib) && null (cSources (libBuildInfo lib))@@ -782,14 +748,12 @@ registerPackage :: Verbosity- -> InstalledPackageInfo- -> PackageDescription- -> LocalBuildInfo- -> Bool+ -> ProgramConfiguration -> PackageDBStack+ -> InstalledPackageInfo -> IO ()-registerPackage verbosity installedPkgInfo _pkg lbi _inplace packageDbs =- HcPkg.reregister (hcPkgInfo $ withPrograms lbi) verbosity packageDbs+registerPackage verbosity progdb packageDbs installedPkgInfo =+ HcPkg.reregister (hcPkgInfo progdb) verbosity packageDbs (Right installedPkgInfo) hcPkgInfo :: ProgramConfiguration -> HcPkg.HcPkgInfo@@ -797,7 +761,10 @@ , HcPkg.noPkgDbStack = False , HcPkg.noVerboseFlag = False , HcPkg.flagPackageConf = False- , HcPkg.useSingleFileDb = True+ , HcPkg.supportsDirDbs = True+ , HcPkg.requiresDirDbs = True+ , HcPkg.nativeMultiInstance = False -- ?+ , HcPkg.recacheMultiInstance = False -- ? } where Just lhcPkgProg = lookupProgram lhcPkgProgram conf
Distribution/Simple/LocalBuildInfo.hs view
@@ -20,14 +20,15 @@ module Distribution.Simple.LocalBuildInfo ( LocalBuildInfo(..), externalPackageDeps,- inplacePackageId,+ localComponentId,+ localUnitId,+ localCompatPackageKey, -- * Buildable package components Component(..), ComponentName(..), showComponentName, ComponentLocalBuildInfo(..),- LibraryName(..), foldComponent, componentName, componentBuildInfo,@@ -62,30 +63,16 @@ prefixRelativeInstallDirs, substPathTemplate, ) import qualified Distribution.Simple.InstallDirs as InstallDirs-import Distribution.Simple.Program (ProgramConfiguration)-import Distribution.InstalledPackageInfo (InstalledPackageInfo)+import Distribution.Simple.Program import Distribution.PackageDescription- ( PackageDescription(..), withLib, Library(libBuildInfo), withExe- , Executable(exeName, buildInfo), withTest, TestSuite(..)- , BuildInfo(buildable), Benchmark(..), ModuleRenaming(..) ) import qualified Distribution.InstalledPackageInfo as Installed import Distribution.Package- ( PackageId, Package(..), InstalledPackageId(..), PackageKey- , PackageName ) import Distribution.Simple.Compiler- ( Compiler, compilerInfo, PackageDBStack, DebugInfoLevel- , OptimisationLevel ) import Distribution.Simple.PackageIndex- ( InstalledPackageIndex, allPackages )-import Distribution.ModuleName ( ModuleName ) import Distribution.Simple.Setup- ( ConfigFlags ) import Distribution.Simple.Utils- ( shortRelativePath ) import Distribution.Text- ( display ) import Distribution.System- ( Platform (..) ) import Data.Array ((!)) import Distribution.Compat.Binary (Binary)@@ -104,6 +91,8 @@ configFlags :: ConfigFlags, -- ^ Options passed to the configuration step. -- Needed to re-run configuration when .cabal is out of date+ flagAssignment :: FlagAssignment,+ -- ^ The final set of flags which were picked for this package extraConfigArgs :: [String], -- ^ Extra args on the command line for the configuration step. -- Needed to re-run configuration when .cabal is out of date@@ -128,10 +117,6 @@ localPkgDescr :: PackageDescription, -- ^ The resolved package description, that does not contain -- any conditionals.- pkgKey :: PackageKey,- -- ^ The package key for the current build, calculated from- -- the package ID and the dependency graph.- instantiatedWith :: [(ModuleName, (InstalledPackageInfo, ModuleName))], withPrograms :: ProgramConfiguration, -- ^Location and args for all programs withPackageDB :: PackageDBStack, -- ^What package database to use, global\/user withVanillaLib:: Bool, -- ^Whether to build normal libs.@@ -139,6 +124,8 @@ withSharedLib :: Bool, -- ^Whether to build shared versions of libs. withDynExe :: Bool, -- ^Whether to link executables dynamically withProfExe :: Bool, -- ^Whether to build executables for profiling.+ withProfLibDetail :: ProfDetailLevel, -- ^Level of automatic profile detail.+ withProfExeDetail :: ProfDetailLevel, -- ^Level of automatic profile detail. withOptimization :: OptimisationLevel, -- ^Whether to build with optimization (if available). withDebugInfo :: DebugInfoLevel, -- ^Whether to emit debug info (if available). withGHCiLib :: Bool, -- ^Whether to build libs suitable for use with GHCi.@@ -152,9 +139,37 @@ instance Binary LocalBuildInfo +-- | Extract the 'ComponentId' from the library component of a+-- 'LocalBuildInfo' if it exists, or make a fake component ID based+-- on the package ID.+localComponentId :: LocalBuildInfo -> ComponentId+localComponentId lbi+ = case localUnitId lbi of+ SimpleUnitId cid -> cid++-- | Extract the 'UnitId' from the library component of a+-- 'LocalBuildInfo' if it exists, or make a fake unit ID based on+-- the package ID.+localUnitId :: LocalBuildInfo -> UnitId+localUnitId lbi =+ foldr go (mkLegacyUnitId (package (localPkgDescr lbi))) (componentsConfigs lbi)+ where go (_, clbi, _) old_uid = case clbi of+ LibComponentLocalBuildInfo { componentUnitId = uid } -> uid+ _ -> old_uid++-- | Extract the compatibility 'ComponentId' from the library component of a+-- 'LocalBuildInfo' if it exists, or make a fake compatibility package+-- key based on the package ID.+localCompatPackageKey :: LocalBuildInfo -> String+localCompatPackageKey lbi =+ foldr go (display (package (localPkgDescr lbi))) (componentsConfigs lbi)+ where go (_, clbi, _) old_pk = case clbi of+ LibComponentLocalBuildInfo { componentCompatPackageKey = pk } -> pk+ _ -> old_pk+ -- | External package dependencies for the package as a whole. This is the -- union of the individual 'componentPackageDeps', less any internal deps.-externalPackageDeps :: LocalBuildInfo -> [(InstalledPackageId, PackageId)]+externalPackageDeps :: LocalBuildInfo -> [(UnitId, PackageId)] externalPackageDeps lbi = -- TODO: what about non-buildable components? nub [ (ipkgid, pkgid)@@ -166,12 +181,6 @@ -- defined in the same package). internal pkgid = pkgid == packageId (localPkgDescr lbi) --- | The installed package Id we use for local packages registered in the local--- package db. This is what is used for intra-package deps between components.----inplacePackageId :: PackageId -> InstalledPackageId-inplacePackageId pkgid = InstalledPackageId (display pkgid ++ "-inplace")- -- ----------------------------------------------------------------------------- -- Buildable components @@ -201,21 +210,22 @@ -- The 'BuildInfo' specifies a set of build dependencies that must be -- satisfied in terms of version ranges. This field fixes those dependencies -- to the specific versions available on this machine for this compiler.- componentPackageDeps :: [(InstalledPackageId, PackageId)],+ componentPackageDeps :: [(UnitId, PackageId)],+ componentUnitId :: UnitId,+ componentCompatPackageKey :: String, componentExposedModules :: [Installed.ExposedModule],- componentPackageRenaming :: Map PackageName ModuleRenaming,- componentLibraries :: [LibraryName]+ componentPackageRenaming :: Map PackageName ModuleRenaming } | ExeComponentLocalBuildInfo {- componentPackageDeps :: [(InstalledPackageId, PackageId)],+ componentPackageDeps :: [(UnitId, PackageId)], componentPackageRenaming :: Map PackageName ModuleRenaming } | TestComponentLocalBuildInfo {- componentPackageDeps :: [(InstalledPackageId, PackageId)],+ componentPackageDeps :: [(UnitId, PackageId)], componentPackageRenaming :: Map PackageName ModuleRenaming } | BenchComponentLocalBuildInfo {- componentPackageDeps :: [(InstalledPackageId, PackageId)],+ componentPackageDeps :: [(UnitId, PackageId)], componentPackageRenaming :: Map PackageName ModuleRenaming } deriving (Generic, Read, Show)@@ -233,11 +243,6 @@ foldComponent _ _ f _ (CTest tst) = f tst foldComponent _ _ _ f (CBench bch) = f bch -data LibraryName = LibraryName String- deriving (Generic, Read, Show)--instance Binary LibraryName- componentBuildInfo :: Component -> BuildInfo componentBuildInfo = foldComponent libBuildInfo buildInfo testBuildInfo benchmarkBuildInfo@@ -306,7 +311,8 @@ ++ "component corresponding to " ++ show cname -getComponentLocalBuildInfo :: LocalBuildInfo -> ComponentName -> ComponentLocalBuildInfo+getComponentLocalBuildInfo :: LocalBuildInfo -> ComponentName+ -> ComponentLocalBuildInfo getComponentLocalBuildInfo lbi cname = case [ clbi | (cname', clbi, _) <- componentsConfigs lbi@@ -361,9 +367,9 @@ | (cname, clbi) <- allComponentsInBuildOrder lbi ] withComponentsInBuildOrder :: PackageDescription -> LocalBuildInfo- -> [ComponentName]- -> (Component -> ComponentLocalBuildInfo -> IO ())- -> IO ()+ -> [ComponentName]+ -> (Component -> ComponentLocalBuildInfo -> IO ())+ -> IO () withComponentsInBuildOrder pkg lbi cnames f = sequence_ [ f (getComponent pkg cname') clbi@@ -476,7 +482,7 @@ absoluteInstallDirs pkg lbi copydest = InstallDirs.absoluteInstallDirs (packageId pkg)- (pkgKey lbi)+ (localUnitId lbi) (compilerInfo (compiler lbi)) copydest (hostPlatform lbi)@@ -488,7 +494,7 @@ prefixRelativeInstallDirs pkg_descr lbi = InstallDirs.prefixRelativeInstallDirs (packageId pkg_descr)- (pkgKey lbi)+ (localUnitId lbi) (compilerInfo (compiler lbi)) (hostPlatform lbi) (installDirTemplates lbi)@@ -499,6 +505,6 @@ . ( InstallDirs.substPathTemplate env ) where env = initialPathTemplateEnv pkgid- (pkgKey lbi)+ (localUnitId lbi) (compilerInfo (compiler lbi)) (hostPlatform lbi)
Distribution/Simple/PackageIndex.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveGeneric #-} -----------------------------------------------------------------------------@@ -17,7 +16,6 @@ -- * Package index data type InstalledPackageIndex, PackageIndex,- FakeMap, -- * Creating an index fromList,@@ -27,7 +25,7 @@ insert, - deleteInstalledPackageId,+ deleteUnitId, deleteSourcePackageId, deletePackageName, -- deleteDependency,@@ -35,7 +33,7 @@ -- * Queries -- ** Precise lookups- lookupInstalledPackageId,+ lookupUnitId, lookupSourcePackageId, lookupPackageId, lookupPackageName,@@ -62,27 +60,26 @@ dependencyGraph, moduleNameIndex, - -- ** Variants of special queries supporting fake map- fakeLookupInstalledPackageId,- brokenPackages',- dependencyClosure',- reverseDependencyClosure',- dependencyInconsistencies',- dependencyCycles',- dependencyGraph',+ -- * Backwards compatibility+ deleteInstalledPackageId,+ lookupInstalledPackageId, ) where +import Distribution.Compat.Binary+import Distribution.Compat.Semigroup as Semi+import Distribution.Package+import Distribution.ModuleName+import qualified Distribution.InstalledPackageInfo as IPI+import Distribution.Version+import Distribution.Simple.Utils+ import Control.Exception (assert) import Data.Array ((!)) import qualified Data.Array as Array-import Distribution.Compat.Binary (Binary) import qualified Data.Graph as Graph import Data.List as List ( null, foldl', sort- , groupBy, sortBy, find, isInfixOf, nubBy, deleteBy, deleteFirstsBy )-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid (Monoid(..))-#endif+ , groupBy, sortBy, find, nubBy, deleteBy, deleteFirstsBy ) import Data.Map (Map) import qualified Data.Map as Map import Data.Maybe (isNothing, fromMaybe)@@ -90,65 +87,17 @@ import GHC.Generics (Generic) import Prelude hiding (lookup) -import Distribution.Package- ( PackageName(..), PackageId- , Package(..), packageName, packageVersion- , Dependency(Dependency)--, --PackageFixedDeps(..)- , InstalledPackageId(..), PackageInstalled(..) )-import Distribution.ModuleName- ( ModuleName )-import Distribution.InstalledPackageInfo- ( InstalledPackageInfo )-import qualified Distribution.InstalledPackageInfo as IPI-import Distribution.Version- ( Version, withinRange )-import Distribution.Simple.Utils (lowercase, comparing, equating)---- Note [FakeMap]--------------------- We'd like to use the PackageIndex defined in this module for--- cabal-install's InstallPlan. However, at the moment, this--- data structure is indexed by InstalledPackageId, which we don't--- know until after we've compiled a package (whereas InstallPlan--- needs to store not-compiled packages in the index.) Eventually,--- an InstalledPackageId will be calculatable prior to actually--- building the package (making it something of a misnomer), but--- at the moment, the "fake installed package ID map" is a workaround--- to solve this problem while reusing PackageIndex. The basic idea--- is that, since we don't know what an InstalledPackageId is--- beforehand, we just fake up one based on the package ID (it only--- needs to be unique for the particular install plan), and fill--- it out with the actual generated InstalledPackageId after the--- package is successfully compiled.------ However, there is a problem: in the index there may be--- references using the old package ID, which are now dangling if--- we update the InstalledPackageId. We could map over the entire--- index to update these pointers as well (a costly operation), but--- instead, we've chosen to parametrize a variety of important functions--- by a FakeMap, which records what a fake installed package ID was--- actually resolved to post-compilation. If we do a lookup, we first--- check and see if it's a fake ID in the FakeMap.------ It's a bit grungy, but we expect this to only be temporary anyway.--- (Another possible workaround would have been to *not* update--- the installed package ID, but I decided this would be hard to--- understand.)---- | Map from fake installed package IDs to real ones. See Note [FakeMap]-type FakeMap = Map InstalledPackageId InstalledPackageId- -- | The collection of information about packages from one or more 'PackageDB's. -- These packages generally should have an instance of 'PackageInstalled' ----- Packages are uniquely identified in by their 'InstalledPackageId', they can+-- Packages are uniquely identified in by their 'UnitId', they can -- also be efficiently looked up by package name or by name and version. -- data PackageIndex a = PackageIndex -- The primary index. Each InstalledPackageInfo record is uniquely identified- -- by its InstalledPackageId.+ -- by its UnitId. --- !(Map InstalledPackageId a)+ !(Map UnitId a) -- This auxiliary index maps package names (case-sensitively) to all the -- versions and instances of that package. This allows us to find all@@ -156,39 +105,42 @@ -- -- It is a three-level index. The first level is the package name, -- the second is the package version and the final level is instances- -- of the same package version. These are unique by InstalledPackageId+ -- of the same package version. These are unique by UnitId -- and are kept in preference order. -- -- FIXME: Clarify what "preference order" means. Check that this invariant is -- preserved. See #1463 for discussion. !(Map PackageName (Map Version [a])) - deriving (Generic, Show, Read)+ deriving (Eq, Generic, Show, Read) instance Binary a => Binary (PackageIndex a) -- | The default package index which contains 'InstalledPackageInfo'. Normally -- use this.-type InstalledPackageIndex = PackageIndex InstalledPackageInfo+type InstalledPackageIndex = PackageIndex IPI.InstalledPackageInfo -instance PackageInstalled a => Monoid (PackageIndex a) where+instance HasUnitId a => Monoid (PackageIndex a) where mempty = PackageIndex Map.empty Map.empty- mappend = merge+ mappend = (Semi.<>) --save one mappend with empty in the common case: mconcat [] = mempty mconcat xs = foldr1 mappend xs -invariant :: PackageInstalled a => PackageIndex a -> Bool+instance HasUnitId a => Semigroup (PackageIndex a) where+ (<>) = merge++invariant :: HasUnitId a => PackageIndex a -> Bool invariant (PackageIndex pids pnames) =- map installedPackageId (Map.elems pids)+ map installedUnitId (Map.elems pids) == sort- [ assert pinstOk (installedPackageId pinst)+ [ assert pinstOk (installedUnitId pinst) | (pname, pvers) <- Map.toList pnames , let pversOk = not (Map.null pvers) , (pver, pinsts) <- assert pversOk $ Map.toList pvers- , let pinsts' = sortBy (comparing installedPackageId) pinsts+ , let pinsts' = sortBy (comparing installedUnitId) pinsts pinstsOk = all (\g -> length g == 1)- (groupBy (equating installedPackageId) pinsts')+ (groupBy (equating installedUnitId) pinsts') , pinst <- assert pinstsOk $ pinsts' , let pinstOk = packageName pinst == pname && packageVersion pinst == pver@@ -199,8 +151,8 @@ -- * Internal helpers -- -mkPackageIndex :: PackageInstalled a- => Map InstalledPackageId a+mkPackageIndex :: HasUnitId a+ => Map UnitId a -> Map PackageName (Map Version [a]) -> PackageIndex a mkPackageIndex pids pnames = assert (invariant index) index@@ -213,13 +165,13 @@ -- | Build an index out of a bunch of packages. ----- If there are duplicates by 'InstalledPackageId' then later ones mask earlier+-- If there are duplicates by 'UnitId' then later ones mask earlier -- ones. ---fromList :: PackageInstalled a => [a] -> PackageIndex a+fromList :: HasUnitId a => [a] -> PackageIndex a fromList pkgs = mkPackageIndex pids pnames where- pids = Map.fromList [ (installedPackageId pkg, pkg) | pkg <- pkgs ]+ pids = Map.fromList [ (installedUnitId pkg, pkg) | pkg <- pkgs ] pnames = Map.fromList [ (packageName (head pkgsN), pvers)@@ -229,7 +181,7 @@ , let pvers = Map.fromList [ (packageVersion (head pkgsNV),- nubBy (equating installedPackageId) (reverse pkgsNV))+ nubBy (equating installedUnitId) (reverse pkgsNV)) | pkgsNV <- groupBy (equating packageVersion) pkgsN ] ]@@ -241,14 +193,15 @@ -- | Merge two indexes. -- -- Packages from the second mask packages from the first if they have the exact--- same 'InstalledPackageId'.+-- same 'UnitId'. -- -- For packages with the same source 'PackageId', packages from the second are -- \"preferred\" over those from the first. Being preferred means they are top -- result when we do a lookup by source 'PackageId'. This is the mechanism we -- use to prefer user packages over global packages. ---merge :: PackageInstalled a => PackageIndex a -> PackageIndex a -> PackageIndex a+merge :: HasUnitId a => PackageIndex a -> PackageIndex a+ -> PackageIndex a merge (PackageIndex pids1 pnames1) (PackageIndex pids2 pnames2) = mkPackageIndex (Map.unionWith (\_ y -> y) pids1 pids2) (Map.unionWith (Map.unionWith mergeBuckets) pnames1 pnames2)@@ -256,7 +209,7 @@ -- Packages in the second list mask those in the first, however preferred -- packages go first in the list. mergeBuckets xs ys = ys ++ (xs \\ ys)- (\\) = deleteFirstsBy (equating installedPackageId)+ (\\) = deleteFirstsBy (equating installedUnitId) -- | Inserts a single package into the index.@@ -264,12 +217,12 @@ -- This is equivalent to (but slightly quicker than) using 'mappend' or -- 'merge' with a singleton index. ---insert :: PackageInstalled a => a -> PackageIndex a -> PackageIndex a+insert :: HasUnitId a => a -> PackageIndex a -> PackageIndex a insert pkg (PackageIndex pids pnames) = mkPackageIndex pids' pnames' where- pids' = Map.insert (installedPackageId pkg) pkg pids+ pids' = Map.insert (installedUnitId pkg) pkg pids pnames' = insertPackageName pnames insertPackageName = Map.insertWith' (\_ -> insertPackageVersion)@@ -281,13 +234,15 @@ (packageVersion pkg) [pkg] insertPackageInstance pkgs =- pkg : deleteBy (equating installedPackageId) pkg pkgs+ pkg : deleteBy (equating installedUnitId) pkg pkgs -- | Removes a single installed package from the index. ---deleteInstalledPackageId :: PackageInstalled a => InstalledPackageId -> PackageIndex a -> PackageIndex a-deleteInstalledPackageId ipkgid original@(PackageIndex pids pnames) =+deleteUnitId :: HasUnitId a+ => UnitId -> PackageIndex a+ -> PackageIndex a+deleteUnitId ipkgid original@(PackageIndex pids pnames) = case Map.updateLookupWithKey (\_ _ -> Nothing) ipkgid pids of (Nothing, _) -> original (Just spkgid, pids') -> mkPackageIndex pids'@@ -303,19 +258,26 @@ deletePkgInstance = (\xs -> if List.null xs then Nothing else Just xs)- . List.deleteBy (\_ pkg -> installedPackageId pkg == ipkgid) undefined+ . List.deleteBy (\_ pkg -> installedUnitId pkg == ipkgid) undefined +-- | Backwards compatibility wrapper for Cabal pre-1.24.+{-# DEPRECATED deleteInstalledPackageId "Use deleteUnitId instead" #-}+deleteInstalledPackageId :: HasUnitId a+ => UnitId -> PackageIndex a+ -> PackageIndex a+deleteInstalledPackageId = deleteUnitId -- | Removes all packages with this source 'PackageId' from the index. ---deleteSourcePackageId :: PackageInstalled a => PackageId -> PackageIndex a -> PackageIndex a+deleteSourcePackageId :: HasUnitId a => PackageId -> PackageIndex a+ -> PackageIndex a deleteSourcePackageId pkgid original@(PackageIndex pids pnames) = case Map.lookup (packageName pkgid) pnames of Nothing -> original Just pvers -> case Map.lookup (packageVersion pkgid) pvers of Nothing -> original Just pkgs -> mkPackageIndex- (foldl' (flip (Map.delete . installedPackageId)) pids pkgs)+ (foldl' (flip (Map.delete . installedUnitId)) pids pkgs) (deletePkgName pnames) where deletePkgName =@@ -328,12 +290,13 @@ -- | Removes all packages with this (case-sensitive) name from the index. ---deletePackageName :: PackageInstalled a => PackageName -> PackageIndex a -> PackageIndex a+deletePackageName :: HasUnitId a => PackageName -> PackageIndex a+ -> PackageIndex a deletePackageName name original@(PackageIndex pids pnames) = case Map.lookup name pnames of Nothing -> original Just pvers -> mkPackageIndex- (foldl' (flip (Map.delete . installedPackageId)) pids+ (foldl' (flip (Map.delete . installedUnitId)) pids (concat (Map.elems pvers))) (Map.delete name pnames) @@ -367,7 +330,8 @@ -- -- They are grouped by source package id (package name and version). ---allPackagesBySourcePackageId :: PackageInstalled a => PackageIndex a -> [(PackageId, [a])]+allPackagesBySourcePackageId :: HasUnitId a => PackageIndex a+ -> [(PackageId, [a])] allPackagesBySourcePackageId (PackageIndex _ pnames) = [ (packageId ipkg, ipkgs) | pvers <- Map.elems pnames@@ -379,21 +343,27 @@ -- | Does a lookup by source package id (name & version). ----- Since multiple package DBs mask each other by 'InstalledPackageId',+-- Since multiple package DBs mask each other by 'UnitId', -- then we get back at most one package. ---lookupInstalledPackageId :: PackageInstalled a => PackageIndex a -> InstalledPackageId+lookupUnitId :: PackageIndex a -> UnitId+ -> Maybe a+lookupUnitId (PackageIndex pids _) pid = Map.lookup pid pids++-- | Backwards compatibility for Cabal pre-1.24.+{-# DEPRECATED lookupInstalledPackageId "Use lookupUnitId instead" #-}+lookupInstalledPackageId :: PackageIndex a -> UnitId -> Maybe a-lookupInstalledPackageId (PackageIndex pids _) pid = Map.lookup pid pids+lookupInstalledPackageId = lookupUnitId -- | Does a lookup by source package id (name & version). -- -- There can be multiple installed packages with the same source 'PackageId'--- but different 'InstalledPackageId'. They are returned in order of+-- but different 'UnitId'. They are returned in order of -- preference, with the most preferred first. ---lookupSourcePackageId :: PackageInstalled a => PackageIndex a -> PackageId -> [a]+lookupSourcePackageId :: PackageIndex a -> PackageId -> [a] lookupSourcePackageId (PackageIndex _ pnames) pkgid = case Map.lookup (packageName pkgid) pnames of Nothing -> []@@ -403,7 +373,7 @@ -- | Convenient alias of 'lookupSourcePackageId', but assuming only -- one package per package ID.-lookupPackageId :: PackageInstalled a => PackageIndex a -> PackageId -> Maybe a+lookupPackageId :: PackageIndex a -> PackageId -> Maybe a lookupPackageId index pkgid = case lookupSourcePackageId index pkgid of [] -> Nothing [pkg] -> Just pkg@@ -411,7 +381,7 @@ -- | Does a lookup by source package name. ---lookupPackageName :: PackageInstalled a => PackageIndex a -> PackageName+lookupPackageName :: PackageIndex a -> PackageName -> [(Version, [a])] lookupPackageName (PackageIndex _ pnames) name = case Map.lookup name pnames of@@ -424,7 +394,7 @@ -- We get back any number of versions of the specified package name, all -- satisfying the version range constraint. ---lookupDependency :: PackageInstalled a => PackageIndex a -> Dependency+lookupDependency :: PackageIndex a -> Dependency -> [(Version, [a])] lookupDependency (PackageIndex _ pnames) (Dependency name versionRange) = case Map.lookup name pnames of@@ -449,7 +419,7 @@ -- packages. The list of ambiguous results is split by exact package name. So -- it is a non-empty list of non-empty lists. ---searchByName :: PackageInstalled a => PackageIndex a -> String -> SearchResult [a]+searchByName :: PackageIndex a -> String -> SearchResult [a] searchByName (PackageIndex _ pnames) name = case [ pkgs | pkgs@(PackageName name',_) <- Map.toList pnames , lowercase name' == lname ] of@@ -466,7 +436,7 @@ -- -- That is, all packages that contain the given string in their name. ---searchByNameSubstring :: PackageInstalled a => PackageIndex a -> String -> [a]+searchByNameSubstring :: PackageIndex a -> String -> [a] searchByNameSubstring (PackageIndex _ pnames) searchterm = [ pkg | (PackageName name, pvers) <- Map.toList pnames@@ -491,14 +461,10 @@ -- other, directly or indirectly. -- dependencyCycles :: PackageInstalled a => PackageIndex a -> [[a]]-dependencyCycles = dependencyCycles' Map.empty---- | Variant of 'dependencyCycles' which accepts a 'FakeMap'. See Note [FakeMap].-dependencyCycles' :: PackageInstalled a => FakeMap -> PackageIndex a -> [[a]]-dependencyCycles' fakeMap index =+dependencyCycles index = [ vs | Graph.CyclicSCC vs <- Graph.stronglyConnComp adjacencyList ] where- adjacencyList = [ (pkg, installedPackageId pkg, fakeInstalledDepends fakeMap pkg)+ adjacencyList = [ (pkg, installedUnitId pkg, installedDepends pkg) | pkg <- allPackages index ] @@ -506,22 +472,15 @@ -- -- Returns such packages along with the dependencies that they're missing. ---brokenPackages :: PackageInstalled a => PackageIndex a -> [(a, [InstalledPackageId])]-brokenPackages = brokenPackages' Map.empty---- | Variant of 'brokenPackages' which accepts a 'FakeMap'. See Note [FakeMap].-brokenPackages' :: PackageInstalled a => FakeMap -> PackageIndex a -> [(a, [InstalledPackageId])]-brokenPackages' fakeMap index =+brokenPackages :: PackageInstalled a => PackageIndex a+ -> [(a, [UnitId])]+brokenPackages index = [ (pkg, missing) | pkg <- allPackages index , let missing = [ pkg' | pkg' <- installedDepends pkg- , isNothing (fakeLookupInstalledPackageId fakeMap index pkg') ]+ , isNothing (lookupUnitId index pkg') ] , not (null missing) ] --- | Variant of 'lookupInstalledPackageId' which accepts a 'FakeMap'. See Note [FakeMap].-fakeLookupInstalledPackageId :: PackageInstalled a => FakeMap -> PackageIndex a -> InstalledPackageId -> Maybe a-fakeLookupInstalledPackageId fakeMap index pkg = lookupInstalledPackageId index (Map.findWithDefault pkg pkg fakeMap)- -- | Tries to take the transitive closure of the package dependencies. -- -- If the transitive closure is complete then it returns that subset of the@@ -531,25 +490,17 @@ -- the original given 'PackageId's do not occur in the index. -- dependencyClosure :: PackageInstalled a => PackageIndex a- -> [InstalledPackageId]- -> Either (PackageIndex a)- [(a, [InstalledPackageId])]-dependencyClosure = dependencyClosure' Map.empty---- | Variant of 'dependencyClosure' which accepts a 'FakeMap'. See Note [FakeMap].-dependencyClosure' :: PackageInstalled a => FakeMap- -> PackageIndex a- -> [InstalledPackageId]+ -> [UnitId] -> Either (PackageIndex a)- [(a, [InstalledPackageId])]-dependencyClosure' fakeMap index pkgids0 = case closure mempty [] pkgids0 of+ [(a, [UnitId])]+dependencyClosure index pkgids0 = case closure mempty [] pkgids0 of (completed, []) -> Left completed (completed, _) -> Right (brokenPackages completed) where closure completed failed [] = (completed, failed)- closure completed failed (pkgid:pkgids) = case fakeLookupInstalledPackageId fakeMap index pkgid of+ closure completed failed (pkgid:pkgids) = case lookupUnitId index pkgid of Nothing -> closure completed (pkgid:failed) pkgids- Just pkg -> case fakeLookupInstalledPackageId fakeMap completed (installedPackageId pkg) of+ Just pkg -> case lookupUnitId completed (installedUnitId pkg) of Just _ -> closure completed failed pkgids Nothing -> closure completed' failed pkgids' where completed' = insert pkg completed@@ -560,23 +511,16 @@ -- * The given 'PackageId's must be in the index. -- reverseDependencyClosure :: PackageInstalled a => PackageIndex a- -> [InstalledPackageId]- -> [a]-reverseDependencyClosure = reverseDependencyClosure' Map.empty---- | Variant of 'reverseDependencyClosure' which accepts a 'FakeMap'. See Note [FakeMap].-reverseDependencyClosure' :: PackageInstalled a => FakeMap- -> PackageIndex a- -> [InstalledPackageId]+ -> [UnitId] -> [a]-reverseDependencyClosure' fakeMap index =+reverseDependencyClosure index = map vertexToPkg . concatMap Tree.flatten . Graph.dfs reverseDepGraph . map (fromMaybe noSuchPkgId . pkgIdToVertex) where- (depGraph, vertexToPkg, pkgIdToVertex) = dependencyGraph' fakeMap index+ (depGraph, vertexToPkg, pkgIdToVertex) = dependencyGraph index reverseDepGraph = Graph.transposeG depGraph noSuchPkgId = error "reverseDependencyClosure: package is not in the graph" @@ -601,25 +545,17 @@ dependencyGraph :: PackageInstalled a => PackageIndex a -> (Graph.Graph, Graph.Vertex -> a,- InstalledPackageId -> Maybe Graph.Vertex)-dependencyGraph = dependencyGraph' Map.empty---- | Variant of 'dependencyGraph' which accepts a 'FakeMap'. See Note [FakeMap].-dependencyGraph' :: PackageInstalled a => FakeMap- -> PackageIndex a- -> (Graph.Graph,- Graph.Vertex -> a,- InstalledPackageId -> Maybe Graph.Vertex)-dependencyGraph' fakeMap index = (graph, vertex_to_pkg, id_to_vertex)+ UnitId -> Maybe Graph.Vertex)+dependencyGraph index = (graph, vertex_to_pkg, id_to_vertex) where graph = Array.listArray bounds [ [ v | Just v <- map id_to_vertex (installedDepends pkg) ] | pkg <- pkgs ] pkgs = sortBy (comparing packageId) (allPackages index)- vertices = zip (map installedPackageId pkgs) [0..]+ vertices = zip (map installedUnitId pkgs) [0..] vertex_map = Map.fromList vertices- id_to_vertex pid = Map.lookup (Map.findWithDefault pid pid fakeMap) vertex_map+ id_to_vertex pid = Map.lookup pid vertex_map vertex_to_pkg vertex = pkgTable ! vertex @@ -639,12 +575,7 @@ -- dependencyInconsistencies :: PackageInstalled a => PackageIndex a -> [(PackageName, [(PackageId, Version)])]-dependencyInconsistencies = dependencyInconsistencies' Map.empty---- | Variant of 'dependencyInconsistencies' which accepts a 'FakeMap'. See Note [FakeMap].-dependencyInconsistencies' :: PackageInstalled a => FakeMap -> PackageIndex a- -> [(PackageName, [(PackageId, Version)])]-dependencyInconsistencies' fakeMap index =+dependencyInconsistencies index = [ (name, [ (pid,packageVersion dep) | (dep,pids) <- uses, pid <- pids]) | (name, ipid_map) <- Map.toList inverseIndex , let uses = Map.elems ipid_map@@ -658,32 +589,29 @@ [ (packageName dep, Map.fromList [(ipid,(dep,[packageId pkg]))]) | pkg <- allPackages index- , ipid <- fakeInstalledDepends fakeMap pkg- , Just dep <- [fakeLookupInstalledPackageId fakeMap index ipid]+ , ipid <- installedDepends pkg+ , Just dep <- [lookupUnitId index ipid] ] reallyIsInconsistent :: PackageInstalled a => [a] -> Bool reallyIsInconsistent [] = False reallyIsInconsistent [_p] = False reallyIsInconsistent [p1, p2] =- let pid1 = installedPackageId p1- pid2 = installedPackageId p2- in Map.findWithDefault pid1 pid1 fakeMap `notElem` fakeInstalledDepends fakeMap p2- && Map.findWithDefault pid2 pid2 fakeMap `notElem` fakeInstalledDepends fakeMap p1+ let pid1 = installedUnitId p1+ pid2 = installedUnitId p2+ in pid1 `notElem` installedDepends p2+ && pid2 `notElem` installedDepends p1 reallyIsInconsistent _ = True --- | Variant of 'installedDepends' which accepts a 'FakeMap'. See Note [FakeMap].-fakeInstalledDepends :: PackageInstalled a => FakeMap -> a -> [InstalledPackageId]-fakeInstalledDepends fakeMap = map (\pid -> Map.findWithDefault pid pid fakeMap) . installedDepends---- | A rough approximation of GHC's module finder, takes a 'InstalledPackageIndex' and--- turns it into a map from module names to their source packages. It's used to--- initialize the @build-deps@ field in @cabal init@.-moduleNameIndex :: InstalledPackageIndex -> Map ModuleName [InstalledPackageInfo]+-- | A rough approximation of GHC's module finder, takes a+-- 'InstalledPackageIndex' and turns it into a map from module names to their+-- source packages. It's used to initialize the @build-deps@ field in @cabal+-- init@.+moduleNameIndex :: InstalledPackageIndex -> Map ModuleName [IPI.InstalledPackageInfo] moduleNameIndex index = Map.fromListWith (++) $ do pkg <- allPackages index- IPI.ExposedModule m reexport _ <- IPI.exposedModules pkg+ IPI.ExposedModule m reexport <- IPI.exposedModules pkg case reexport of Nothing -> return (m, [pkg]) Just (IPI.OriginalModule _ m') | m == m' -> []
Distribution/Simple/PreProcess.hs view
@@ -17,8 +17,9 @@ -- handlers. This module is not as good as it could be, it could really do with -- a rewrite to address some of the problems we have with pre-processors. -module Distribution.Simple.PreProcess (preprocessComponent, knownSuffixHandlers,- ppSuffixes, PPSuffixHandler, PreProcessor(..),+module Distribution.Simple.PreProcess (preprocessComponent, preprocessExtras,+ knownSuffixHandlers, ppSuffixes,+ PPSuffixHandler, PreProcessor(..), mkSimplePreProcessor, runSimplePreProcessor, ppCpp, ppCpp', ppGreenCard, ppC2hs, ppHsc2hs, ppHappy, ppAlex, ppUnlit, platformDefines@@ -26,54 +27,32 @@ where -import Control.Monad-import Distribution.Simple.PreProcess.Unlit (unlit)+import Distribution.Simple.PreProcess.Unlit import Distribution.Package- ( Package(..), PackageName(..) ) import qualified Distribution.ModuleName as ModuleName import Distribution.PackageDescription as PD- ( PackageDescription(..), BuildInfo(..)- , Executable(..)- , Library(..), libModules- , TestSuite(..), testModules- , TestSuiteInterface(..)- , Benchmark(..), benchmarkModules, BenchmarkInterface(..) ) import qualified Distribution.InstalledPackageInfo as Installed- ( InstalledPackageInfo_(..) ) import qualified Distribution.Simple.PackageIndex as PackageIndex import Distribution.Simple.CCompiler- ( cSourceExtensions ) import Distribution.Simple.Compiler- ( CompilerFlavor(..)- , compilerFlavor, compilerCompatVersion, compilerVersion ) import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), Component(..) )-import Distribution.Simple.BuildPaths (autogenModulesDir,cppHeaderName)+import Distribution.Simple.BuildPaths import Distribution.Simple.Utils- ( createDirectoryIfMissingVerbose, withUTF8FileContents, writeUTF8File- , die, setupMessage, intercalate, copyFileVerbose, moreRecentFile- , findFileWithExtension, findFileWithExtension' ) import Distribution.Simple.Program- ( Program(..), ConfiguredProgram(..), programPath- , requireProgram, requireProgramVersion- , rawSystemProgramConf, rawSystemProgram- , greencardProgram, cpphsProgram, hsc2hsProgram, c2hsProgram- , happyProgram, alexProgram, ghcProgram, ghcjsProgram, gccProgram ) import Distribution.Simple.Test.LibV09- ( writeSimpleTestStub, stubFilePath, stubName ) import Distribution.System- ( OS(..), buildOS, Arch(..), Platform(..) ) import Distribution.Text import Distribution.Version- ( Version(..), anyVersion, orLaterVersion ) import Distribution.Verbosity +import Control.Monad import Data.Maybe (fromMaybe)-import Data.List (nub)+import Data.List (nub, isSuffixOf) import System.Directory (doesFileExist) import System.Info (os, arch) import System.FilePath (splitExtension, dropExtensions, (</>), (<.>),- takeDirectory, normalise, replaceExtension)+ takeDirectory, normalise, replaceExtension,+ takeExtensions) -- |The interface to a preprocessor, which may be implemented using an -- external program, but need not be. The arguments are the name of@@ -129,6 +108,13 @@ -> IO () -- Should exit if the preprocessor fails } +-- | Function to determine paths to possible extra C sources for a+-- preprocessor: just takes the path to the build directory and uses+-- this to search for C sources with names that match the+-- preprocessor's output name format.+type PreProcessorExtras = FilePath -> IO [FilePath]++ mkSimplePreProcessor :: (FilePath -> FilePath -> Verbosity -> IO ()) -> (FilePath, FilePath) -> (FilePath, FilePath) -> Verbosity -> IO ()@@ -251,7 +237,7 @@ Just (psrcLoc, psrcRelFile) -> do let (srcStem, ext) = splitExtension psrcRelFile psrcFile = psrcLoc </> psrcRelFile- pp = fromMaybe (error "Internal error in preProcess module: Just expected")+ pp = fromMaybe (error "Distribution.Simple.PreProcess: Just expected") (lookup (tailNotNull ext) handlers) -- Preprocessing files for 'sdist' is different from preprocessing -- for 'build'. When preprocessing for sdist we preprocess to@@ -438,9 +424,15 @@ ++ ["-o", outFile, inFile] } where+ -- TODO: installedPkgs contains ALL dependencies associated with+ -- the package, but we really only want to look at packages for the+ -- *current* dependency. We should use PackageIndex.dependencyClosure+ -- on the direct depends of the component. Can't easily do that,+ -- because the signature of this function is wrong. Tracked with+ -- #2971 (which has a test case.) pkgs = PackageIndex.topologicalOrder (packageHacks (installedPkgs lbi)) isOSX = case buildOS of OSX -> True; _ -> False- isELF = case buildOS of OSX -> False; Windows -> False; _ -> True;+ isELF = case buildOS of OSX -> False; Windows -> False; AIX -> False; _ -> True; packageHacks = case compilerFlavor (compiler lbi) of GHC -> hackRtsPackage GHCJS -> hackRtsPackage@@ -455,6 +447,9 @@ -> PackageIndex.insert rts { Installed.ldOptions = [] } index _ -> error "No (or multiple) ghc rts package is registered!!" +ppHsc2hsExtras :: PreProcessorExtras+ppHsc2hsExtras buildBaseDir = filter ("_hsc.c" `isSuffixOf`) `fmap`+ getDirectoryContentsRecursive buildBaseDir ppC2hs :: BuildInfo -> LocalBuildInfo -> PreProcessor ppC2hs bi lbi =@@ -471,6 +466,7 @@ -- Options from the current package: [ "--cpp=" ++ programPath gccProg, "--cppopts=-E" ] ++ [ "--cppopts=" ++ opt | opt <- getCppOptions bi lbi ]+ ++ [ "--cppopts=-include" ++ (autogenModulesDir lbi </> cppHeaderName) ] ++ [ "--include=" ++ outBaseDir ] -- Options from dependent packages@@ -490,6 +486,10 @@ where pkgs = PackageIndex.topologicalOrder (installedPkgs lbi) +ppC2hsExtras :: PreProcessorExtras+ppC2hsExtras d = filter (\p -> takeExtensions p == ".chs.c") `fmap`+ getDirectoryContentsRecursive d+ --TODO: perhaps use this with hsc2hs too --TODO: remove cc-options from cpphs for cabal-version: >= 1.10 getCppOptions :: BuildInfo -> LocalBuildInfo -> [String]@@ -557,7 +557,9 @@ IRIX -> ["irix"] HaLVM -> [] IOS -> ["ios"]+ Android -> ["android"] Ghcjs -> ["ghcjs"]+ Hurd -> ["hurd"] OtherOS _ -> [] archStr = case hostArch of I386 -> ["i386"]@@ -618,3 +620,33 @@ , ("ly", ppHappy) , ("cpphs", ppCpp) ]++-- |Standard preprocessors with possible extra C sources: c2hs, hsc2hs.+knownExtrasHandlers :: [ PreProcessorExtras ]+knownExtrasHandlers = [ ppC2hsExtras, ppHsc2hsExtras ]++-- | Find any extra C sources generated by preprocessing that need to+-- be added to the component (addresses issue #238).+preprocessExtras :: Component+ -> LocalBuildInfo+ -> IO [FilePath]+preprocessExtras comp lbi = case comp of+ CLib _ -> pp $ buildDir lbi+ (CExe Executable { exeName = nm }) ->+ pp $ buildDir lbi </> nm </> nm ++ "-tmp"+ CTest test -> do+ case testInterface test of+ TestSuiteExeV10 _ _ ->+ pp $ buildDir lbi </> testName test </> testName test ++ "-tmp"+ TestSuiteLibV09 _ _ ->+ pp $ buildDir lbi </> stubName test </> stubName test ++ "-tmp"+ TestSuiteUnsupported tt -> die $ "No support for preprocessing test "+ ++ "suite type " ++ display tt+ CBench bm -> do+ case benchmarkInterface bm of+ BenchmarkExeV10 _ _ ->+ pp $ buildDir lbi </> benchmarkName bm </> benchmarkName bm ++ "-tmp"+ BenchmarkUnsupported tt -> die $ "No support for preprocessing benchmark "+ ++ "type " ++ display tt+ where+ pp dir = (map (dir </>) . concat) `fmap` forM knownExtrasHandlers ($ dir)
Distribution/Simple/Program.hs view
@@ -38,7 +38,8 @@ , ProgramSearchPath , ProgramSearchPathEntry(..) , simpleProgram- , findProgramLocation+ , findProgramOnSearchPath+ , defaultProgramSearchPath , findProgramVersion -- * Configured program and related functions@@ -122,6 +123,7 @@ , rawSystemProgramConf , rawSystemProgramStdoutConf , findProgramOnPath+ , findProgramLocation ) where @@ -129,11 +131,9 @@ import Distribution.Simple.Program.Run import Distribution.Simple.Program.Db import Distribution.Simple.Program.Builtin-+import Distribution.Simple.Program.Find import Distribution.Simple.Utils- ( die, findProgramLocation, findProgramVersion ) import Distribution.Verbosity- ( Verbosity ) -- | Runs the given configured program.@@ -217,6 +217,8 @@ -> ProgramConfiguration restoreProgramConfiguration = restoreProgramDb -{-# DEPRECATED findProgramOnPath "use findProgramLocation instead" #-}+{-# DEPRECATED findProgramOnPath "use findProgramOnSearchPath instead" #-} findProgramOnPath :: String -> Verbosity -> IO (Maybe FilePath)-findProgramOnPath = flip findProgramLocation+findProgramOnPath name verbosity =+ fmap (fmap fst) $+ findProgramOnSearchPath verbosity defaultProgramSearchPath name
Distribution/Simple/Program/Ar.hs view
@@ -15,7 +15,7 @@ multiStageProgramInvocation ) where -import Control.Monad (when, unless)+import Control.Monad (unless) import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BS8 import Data.Char (isSpace)@@ -26,8 +26,6 @@ import Distribution.Simple.Program.Run ( programInvocation, multiStageProgramInvocation , runProgramInvocation )-import qualified Distribution.Simple.Program.Strip as Strip- ( stripLib ) import Distribution.Simple.Utils ( dieWithLocation, withTempDirectory ) import Distribution.System@@ -86,16 +84,15 @@ | inv <- multiStageProgramInvocation simple (initial, middle, final) files ] - when stripLib $ Strip.stripLib verbosity platform progConf tmpPath- unless (hostArch == Arm) $ -- See #1537+ unless (hostArch == Arm -- See #1537+ || hostOS == AIX) $ -- AIX uses its own "ar" format variant wipeMetadata tmpPath equal <- filesEqual tmpPath targetPath unless equal $ renameFile tmpPath targetPath where progConf = withPrograms lbi- stripLib = stripLibs lbi- platform@(Platform hostArch hostOS) = hostPlatform lbi+ Platform hostArch hostOS = hostPlatform lbi verbosityOpts v | v >= deafening = ["-v"] | v >= verbose = [] | otherwise = ["-c"]
Distribution/Simple/Program/Builtin.hs view
@@ -46,25 +46,16 @@ ) where import Distribution.Simple.Program.Find- ( findProgramOnSearchPath )+import Distribution.Simple.Program.Internal import Distribution.Simple.Program.Run- ( getProgramInvocationOutput, programInvocation ) import Distribution.Simple.Program.Types- ( Program(..), ConfiguredProgram(..), simpleProgram ) import Distribution.Simple.Utils- ( findProgramVersion ) import Distribution.Compat.Exception- ( catchIO ) import Distribution.Verbosity- ( lessVerbose ) import Distribution.Version- ( Version(..), withinRange, earlierVersion, laterVersion- , intersectVersionRanges )+ import Data.Char ( isDigit )--import Data.List- ( isInfixOf ) import qualified Data.Map as Map -- ------------------------------------------------------------@@ -225,16 +216,16 @@ haskellSuiteProgram = (simpleProgram "haskell-suite") { -- pretend that the program exists, otherwise it won't be in the -- "configured" state- programFindLocation =- \_verbosity _searchPath -> return $ Just "haskell-suite-dummy-location"+ programFindLocation = \_verbosity _searchPath ->+ return $ Just ("haskell-suite-dummy-location", []) } -- This represent a haskell-suite package manager. See the comments for -- haskellSuiteProgram. haskellSuitePkgProgram :: Program haskellSuitePkgProgram = (simpleProgram "haskell-suite-pkg") {- programFindLocation =- \_verbosity _searchPath -> return $ Just "haskell-suite-pkg-dummy-location"+ programFindLocation = \_verbosity _searchPath ->+ return $ Just ("haskell-suite-pkg-dummy-location", []) } @@ -269,24 +260,8 @@ stripProgram :: Program stripProgram = (simpleProgram "strip") { programFindVersion = \verbosity ->- findProgramVersion "--version" selectVersion (lessVerbose verbosity)+ findProgramVersion "--version" stripExtractVersion (lessVerbose verbosity) }- where- selectVersion str =- -- Invoking "strip --version" gives very inconsistent- -- results. We look for the first word that starts with a- -- number, and try parsing out the first two components of- -- it. Non-GNU 'strip' doesn't appear to have a version flag.- let numeric "" = False- numeric (x:_) = isDigit x- in case dropWhile (not . numeric) (words str) of- (ver:_) ->- -- take the first two version components- let isDot = (== '.')- (major, rest) = break isDot ver- minor = takeWhile (not . isDot) (dropWhile isDot rest)- in major ++ "." ++ minor- _ -> "" hsc2hsProgram :: Program hsc2hsProgram = (simpleProgram "hsc2hs") {
Distribution/Simple/Program/Db.hs view
@@ -1,6 +1,3 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveGeneric #-}- ----------------------------------------------------------------------------- -- | -- Module : Distribution.Simple.Program.Db@@ -59,29 +56,19 @@ ) where import Distribution.Simple.Program.Types- ( Program(..), ProgArg, ConfiguredProgram(..), ProgramLocation(..) ) import Distribution.Simple.Program.Find- ( ProgramSearchPath, defaultProgramSearchPath- , findProgramOnSearchPath, programSearchPathAsPATHVar ) import Distribution.Simple.Program.Builtin- ( builtinPrograms ) import Distribution.Simple.Utils- ( die, doesExecutableExist ) import Distribution.Version- ( Version, VersionRange, isAnyVersion, withinRange ) import Distribution.Text- ( display ) import Distribution.Verbosity- ( Verbosity )+import Distribution.Compat.Binary -import Distribution.Compat.Binary (Binary(..))-#if __GLASGOW_HASKELL__ < 710-import Data.Functor ((<$>))-#endif import Data.List ( foldl' ) import Data.Maybe ( catMaybes )+import Data.Tuple (swap) import qualified Data.Map as Map import Control.Monad ( join, foldM )@@ -129,28 +116,42 @@ -- Read & Show instances are based on listToFM--- Note that we only serialise the configured part of the database, this is--- because we don't need the unconfigured part after the configure stage, and--- additionally because we cannot read/show 'Program' as it contains functions.++-- | Note that this instance does not preserve the known 'Program's.+-- See 'restoreProgramDb' for details.+-- instance Show ProgramDb where show = show . Map.toAscList . configuredProgs +-- | Note that this instance does not preserve the known 'Program's.+-- See 'restoreProgramDb' for details.+-- instance Read ProgramDb where readsPrec p s = [ (emptyProgramDb { configuredProgs = Map.fromList s' }, r) | (s', r) <- readsPrec p s ] +-- | Note that this instance does not preserve the known 'Program's.+-- See 'restoreProgramDb' for details.+-- instance Binary ProgramDb where- put = put . configuredProgs+ put db = do+ put (progSearchPath db)+ put (configuredProgs db)+ get = do- progs <- get- return $! emptyProgramDb { configuredProgs = progs }+ searchpath <- get+ progs <- get+ return $! emptyProgramDb {+ progSearchPath = searchpath,+ configuredProgs = progs+ } --- | The Read\/Show instance does not preserve all the unconfigured 'Programs'--- because 'Program' is not in Read\/Show because it contains functions. So to--- fully restore a deserialised 'ProgramDb' use this function to add--- back all the known 'Program's.+-- | The 'Read'\/'Show' and 'Binary' instances do not preserve all the+-- unconfigured 'Programs' because 'Program' is not in 'Read'\/'Show' because+-- it contains functions. So to fully restore a deserialised 'ProgramDb' use+-- this function to add back all the known 'Program's. -- -- * It does not add the default programs, but you probably want them, use -- 'builtinPrograms' in addition to any extra you might need.@@ -319,21 +320,23 @@ configureProgram verbosity prog conf = do let name = programName prog maybeLocation <- case userSpecifiedPath prog conf of- Nothing -> programFindLocation prog verbosity (progSearchPath conf)- >>= return . fmap FoundOnSystem+ Nothing ->+ programFindLocation prog verbosity (progSearchPath conf)+ >>= return . fmap (swap . fmap FoundOnSystem . swap) Just path -> do absolute <- doesExecutableExist path if absolute- then return (Just (UserSpecified path))+ then return (Just (UserSpecified path, [])) else findProgramOnSearchPath verbosity (progSearchPath conf) path- >>= maybe (die notFound) (return . Just . UserSpecified)+ >>= maybe (die notFound)+ (return . Just . swap . fmap UserSpecified . swap) where notFound = "Cannot find the program '" ++ name ++ "'. User-specified path '" ++ path ++ "' does not refer to an executable and " ++ "the program is not on the system path." case maybeLocation of Nothing -> return conf- Just location -> do+ Just (location, triedLocations) -> do version <- programFindVersion prog verbosity (locationPath location) newPath <- programSearchPathAsPATHVar (progSearchPath conf) let configuredProg = ConfiguredProgram {@@ -343,7 +346,8 @@ programOverrideArgs = userSpecifiedArgs prog conf, programOverrideEnv = [("PATH", Just newPath)], programProperties = Map.empty,- programLocation = location+ programLocation = location,+ programMonitorFiles = triedLocations } configuredProg' <- programPostConf prog verbosity configuredProg return (updateConfiguredProgs (Map.insert name configuredProg') conf)@@ -443,7 +447,7 @@ | otherwise -> return $! Left (badVersion version location) Nothing ->- return $! Left (noVersion location)+ return $! Left (unknownVersion location) where notFound = "The program '" ++ programName prog ++ "'" ++ versionRequirement@@ -452,7 +456,7 @@ ++ programName prog ++ "'" ++ versionRequirement ++ " is required but the version found at " ++ locationPath l ++ " is version " ++ display v- noVersion l = "The program '"+ unknownVersion l = "The program '" ++ programName prog ++ "'" ++ versionRequirement ++ " is required but the version of " ++ locationPath l ++ " could not be determined."@@ -467,5 +471,5 @@ -> ProgramDb -> IO (ConfiguredProgram, Version, ProgramDb) requireProgramVersion verbosity prog range programDb =- join $ either die return <$>+ join $ either die return `fmap` lookupProgramVersion verbosity prog range programDb
Distribution/Simple/Program/Find.hs view
@@ -1,6 +1,8 @@+{-# LANGUAGE CPP, DeriveGeneric #-}+ ----------------------------------------------------------------------------- -- |--- Module : Distribution.Simple.Program.Types+-- Module : Distribution.Simple.Program.Find -- Copyright : Duncan Coutts 2013 -- -- Maintainer : cabal-devel@haskell.org@@ -26,23 +28,26 @@ defaultProgramSearchPath, findProgramOnSearchPath, programSearchPathAsPATHVar,+ getSystemSearchPath, ) where import Distribution.Verbosity- ( Verbosity ) import Distribution.Simple.Utils- ( debug, doesExecutableExist ) import Distribution.System- ( OS(..), buildOS )-import System.Directory- ( findExecutable ) import Distribution.Compat.Environment- ( getEnvironment )-import System.FilePath- ( (</>), (<.>), splitSearchPath, searchPathSeparator )-import Data.List- ( intercalate )+import Distribution.Compat.Binary +import qualified System.Directory as Directory+ ( findExecutable )+import System.FilePath as FilePath+ ( (</>), (<.>), splitSearchPath, searchPathSeparator, getSearchPath+ , takeDirectory )+import Data.List+ ( nub )+import GHC.Generics+#if defined(mingw32_HOST_OS)+import qualified System.Win32 as Win32+#endif -- | A search path to use when locating executables. This is analogous -- to the unix @$PATH@ or win32 @%PATH%@ but with the ability to use@@ -60,58 +65,69 @@ data ProgramSearchPathEntry = ProgramSearchPathDir FilePath -- ^ A specific dir | ProgramSearchPathDefault -- ^ The system default+ deriving (Eq, Generic) +instance Binary ProgramSearchPathEntry+ defaultProgramSearchPath :: ProgramSearchPath defaultProgramSearchPath = [ProgramSearchPathDefault] findProgramOnSearchPath :: Verbosity -> ProgramSearchPath- -> FilePath -> IO (Maybe FilePath)+ -> FilePath -> IO (Maybe (FilePath, [FilePath])) findProgramOnSearchPath verbosity searchpath prog = do debug verbosity $ "Searching for " ++ prog ++ " in path."- res <- tryPathElems searchpath+ res <- tryPathElems [] searchpath case res of Nothing -> debug verbosity ("Cannot find " ++ prog ++ " on the path")- Just path -> debug verbosity ("Found " ++ prog ++ " at "++ path)+ Just (path, _) -> debug verbosity ("Found " ++ prog ++ " at "++ path) return res where- tryPathElems [] = return Nothing- tryPathElems (pe:pes) = do+ tryPathElems :: [[FilePath]] -> [ProgramSearchPathEntry]+ -> IO (Maybe (FilePath, [FilePath]))+ tryPathElems _ [] = return Nothing+ tryPathElems tried (pe:pes) = do res <- tryPathElem pe case res of- Nothing -> tryPathElems pes- Just _ -> return res+ (Nothing, notfoundat) -> tryPathElems (notfoundat : tried) pes+ (Just foundat, notfoundat) -> return (Just (foundat, alltried))+ where+ alltried = concat (reverse (notfoundat : tried)) + tryPathElem :: ProgramSearchPathEntry -> IO (Maybe FilePath, [FilePath]) tryPathElem (ProgramSearchPathDir dir) =- findFirstExe [ dir </> prog <.> ext | ext <- extensions ]- where- -- Possible improvement: on Windows, read the list of extensions from- -- the PATHEXT environment variable. By default PATHEXT is ".com; .exe;- -- .bat; .cmd".- extensions = case buildOS of- Windows -> ["", "exe"]- Ghcjs -> ["", "exe"]- _ -> [""]+ findFirstExe [ dir </> prog <.> ext | ext <- exeExtensions ] - tryPathElem ProgramSearchPathDefault = do- -- 'findExecutable' doesn't check that the path really refers to an- -- executable on Windows (at least with GHC < 7.8). See- -- https://ghc.haskell.org/trac/ghc/ticket/2184- mExe <- findExecutable prog+ -- On windows, getSystemSearchPath is not guaranteed 100% correct so we+ -- use findExecutable and then approximate the not-found-at locations.+ tryPathElem ProgramSearchPathDefault | buildOS == Windows = do+ mExe <- findExecutable prog+ syspath <- getSystemSearchPath case mExe of- Just exe -> do- exeExists <- doesExecutableExist exe- if exeExists- then return mExe- else return Nothing- _ -> return mExe+ Nothing ->+ let notfoundat = [ dir </> prog | dir <- syspath ] in+ return (Nothing, notfoundat) - findFirstExe [] = return Nothing- findFirstExe (f:fs) = do- isExe <- doesExecutableExist f- if isExe- then return (Just f)- else findFirstExe fs+ Just foundat -> do+ let founddir = takeDirectory foundat+ notfoundat = [ dir </> prog+ | dir <- takeWhile (/= founddir) syspath ]+ return (Just foundat, notfoundat) + -- On other OSs we can just do the simple thing+ tryPathElem ProgramSearchPathDefault = do+ dirs <- getSystemSearchPath+ findFirstExe [ dir </> prog <.> ext | dir <- dirs, ext <- exeExtensions ]++ findFirstExe :: [FilePath] -> IO (Maybe FilePath, [FilePath])+ findFirstExe = go []+ where+ go fs' [] = return (Nothing, reverse fs')+ go fs' (f:fs) = do+ isExe <- doesExecutableExist f+ if isExe+ then return (Just f, reverse fs')+ else go (f:fs') fs+ -- | Interpret a 'ProgramSearchPath' to construct a new @$PATH@ env var. -- Note that this is close but not perfect because on Windows the search -- algorithm looks at more than just the @%PATH%@.@@ -124,3 +140,46 @@ getEntries ProgramSearchPathDefault = do env <- getEnvironment return (maybe [] splitSearchPath (lookup "PATH" env))++-- | Get the system search path. On Unix systems this is just the @$PATH@ env+-- var, but on windows it's a bit more complicated.+--+getSystemSearchPath :: IO [FilePath]+getSystemSearchPath = fmap nub $ do+#if defined(mingw32_HOST_OS)+ processdir <- takeDirectory `fmap` Win32.getModuleFileName Win32.nullHANDLE+ currentdir <- Win32.getCurrentDirectory+ systemdir <- Win32.getSystemDirectory+ windowsdir <- Win32.getWindowsDirectory+ pathdirs <- FilePath.getSearchPath+ let path = processdir : currentdir+ : systemdir : windowsdir+ : pathdirs+ return path+#else+ FilePath.getSearchPath+#endif++#ifdef MIN_VERSION_directory+#if MIN_VERSION_directory(1,2,1)+#define HAVE_directory_121+#endif+#endif++findExecutable :: FilePath -> IO (Maybe FilePath)+#ifdef HAVE_directory_121+findExecutable = Directory.findExecutable+#else+findExecutable prog = do+ -- With directory < 1.2.1 'findExecutable' doesn't check that the path+ -- really refers to an executable.+ mExe <- Directory.findExecutable prog+ case mExe of+ Just exe -> do+ exeExists <- doesExecutableExist exe+ if exeExists+ then return mExe+ else return Nothing+ _ -> return mExe+#endif+
Distribution/Simple/Program/GHC.hs view
@@ -1,9 +1,11 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}+ module Distribution.Simple.Program.GHC ( GhcOptions(..), GhcMode(..), GhcOptimisation(..), GhcDynLinkMode(..),+ GhcProfAuto(..), ghcInvocation, renderGhcOptions,@@ -12,25 +14,23 @@ ) where -import Distribution.Simple.GHC.ImplInfo ( getImplInfo, GhcImplInfo(..) )+import Distribution.Compat.Semigroup as Semi+import Distribution.Simple.GHC.ImplInfo import Distribution.Package import Distribution.PackageDescription hiding (Flag) import Distribution.ModuleName import Distribution.Simple.Compiler hiding (Flag)-import Distribution.Simple.Setup ( Flag(..), flagToMaybe, fromFlagOrDefault,- flagToList )+import Distribution.Simple.Setup import Distribution.Simple.Program.Types import Distribution.Simple.Program.Run+import Distribution.System import Distribution.Text import Distribution.Verbosity-import Distribution.Utils.NubList ( NubListR, fromNubListR )-import Language.Haskell.Extension ( Language(..), Extension(..) )+import Distribution.Utils.NubList+import Language.Haskell.Extension +import GHC.Generics (Generic) import qualified Data.Map as M-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid-#endif-import Data.List ( intercalate ) -- | A structured set of GHC options/flags --@@ -73,9 +73,12 @@ ------------- -- Packages - -- | The package key the modules will belong to; the @ghc -this-package-key@- -- flag.- ghcOptPackageKey :: Flag PackageKey,+ -- | The unit ID the modules will belong to; the @ghc -this-unit-id@+ -- flag (or @-this-package-key@ or @-package-name@ on older+ -- versions of GHC). This is a 'String' because we assume you've+ -- already figured out what the correct format for this string is+ -- (we need to handle backwards compatibility.)+ ghcOptThisUnitId :: Flag String, -- | GHC package databases to use, the @ghc -package-conf@ flag. ghcOptPackageDBs :: PackageDBStack,@@ -84,7 +87,7 @@ -- requires both the short and long form of the package id; -- the @ghc -package@ or @ghc -package-id@ flags. ghcOptPackages ::- NubListR (InstalledPackageId, PackageId, ModuleRenaming),+ NubListR (UnitId, PackageId, ModuleRenaming), -- | Start with a clean package set; the @ghc -hide-all-packages@ flag ghcOptHideAllPackages :: Flag Bool,@@ -93,9 +96,6 @@ -- -no-auto-link-packages@ flag. ghcOptNoAutoLinkPackages :: Flag Bool, - -- | What packages are implementing the signatures- ghcOptSigOf :: [(ModuleName, (PackageKey, ModuleName))],- ----------------- -- Linker stuff @@ -111,6 +111,10 @@ -- | OSX only: frameworks to link in; the @ghc -framework@ flag. ghcOptLinkFrameworks :: NubListR String, + -- | OSX only: Search path for frameworks to link in; the+ -- @ghc -framework-path@ flag.+ ghcOptLinkFrameworkDirs :: NubListR String,+ -- | Don't do the link step, useful in make mode; the @ghc -no-link@ flag. ghcOptNoLink :: Flag Bool, @@ -161,6 +165,9 @@ -- | Compile in profiling mode; the @ghc -prof@ flag. ghcOptProfilingMode :: Flag Bool, + -- | Automatically add profiling cost centers; the @ghc -fprof-auto*@ flags.+ ghcOptProfilingAuto :: Flag GhcProfAuto,+ -- | Use the \"split object files\" feature; the @ghc -split-objs@ flag. ghcOptSplitObjs :: Flag Bool, @@ -207,7 +214,7 @@ -- Modifies some of the GHC error messages. ghcOptCabal :: Flag Bool -} deriving Show+} deriving (Show, Generic) data GhcMode = GhcModeCompile -- ^ @ghc -c@@@ -230,18 +237,24 @@ | GhcStaticAndDynamic -- ^ @-static -dynamic-too@ deriving (Show, Eq) +data GhcProfAuto = GhcProfAutoAll -- ^ @-fprof-auto@+ | GhcProfAutoToplevel -- ^ @-fprof-auto-top@+ | GhcProfAutoExported -- ^ @-fprof-auto-exported@+ deriving (Show, Eq) -runGHC :: Verbosity -> ConfiguredProgram -> Compiler -> GhcOptions -> IO ()-runGHC verbosity ghcProg comp opts = do- runProgramInvocation verbosity (ghcInvocation ghcProg comp opts)+runGHC :: Verbosity -> ConfiguredProgram -> Compiler -> Platform -> GhcOptions+ -> IO ()+runGHC verbosity ghcProg comp platform opts = do+ runProgramInvocation verbosity (ghcInvocation ghcProg comp platform opts) -ghcInvocation :: ConfiguredProgram -> Compiler -> GhcOptions -> ProgramInvocation-ghcInvocation prog comp opts =- programInvocation prog (renderGhcOptions comp opts)+ghcInvocation :: ConfiguredProgram -> Compiler -> Platform -> GhcOptions+ -> ProgramInvocation+ghcInvocation prog comp platform opts =+ programInvocation prog (renderGhcOptions comp platform opts) -renderGhcOptions :: Compiler -> GhcOptions -> [String]-renderGhcOptions comp opts+renderGhcOptions :: Compiler -> Platform -> GhcOptions -> [String]+renderGhcOptions comp _platform@(Platform _arch os) opts | compilerFlavor comp `notElem` [GHC, GHCJS] = error $ "Distribution.Simple.Program.GHC.renderGhcOptions: " ++ "compiler flavor must be 'GHC' or 'GHCJS'!"@@ -283,6 +296,20 @@ , [ "-prof" | flagBool ghcOptProfilingMode ] + , case flagToMaybe (ghcOptProfilingAuto opts) of+ _ | not (flagBool ghcOptProfilingMode)+ -> []+ Nothing -> []+ Just GhcProfAutoAll+ | flagProfAuto implInfo -> ["-fprof-auto"]+ | otherwise -> ["-auto-all"] -- not the same, but close+ Just GhcProfAutoToplevel+ | flagProfAuto implInfo -> ["-fprof-auto-top"]+ | otherwise -> ["-auto-all"]+ Just GhcProfAutoExported+ | flagProfAuto implInfo -> ["-fprof-auto-exported"]+ | otherwise -> ["-auto"]+ , [ "-split-objs" | flagBool ghcOptSplitObjs ] , case flagToMaybe (ghcOptHPCDir opts) of@@ -345,7 +372,14 @@ , [ "-optl" ++ opt | opt <- flags ghcOptLinkOptions ] , ["-l" ++ lib | lib <- flags ghcOptLinkLibs ] , ["-L" ++ dir | dir <- flags ghcOptLinkLibPath ]- , concat [ ["-framework", fmwk] | fmwk <- flags ghcOptLinkFrameworks ]+ , if isOSX+ then concat [ ["-framework", fmwk]+ | fmwk <- flags ghcOptLinkFrameworks ]+ else []+ , if isOSX+ then concat [ ["-framework-path", path]+ | path <- flags ghcOptLinkFrameworkDirs ]+ else [] , [ "-no-hs-main" | flagBool ghcOptLinkNoHsMain ] , [ "-dynload deploy" | not (null (flags ghcOptRPaths)) ] , concat [ [ "-optl-Wl,-rpath," ++ dir]@@ -354,25 +388,18 @@ ------------- -- Packages - , concat [ [if packageKeySupported comp- then "-this-package-key"- else "-package-name", display pkgid]- | pkgid <- flag ghcOptPackageKey ]+ , concat [ [ case () of+ _ | unitIdSupported comp -> "-this-unit-id"+ | packageKeySupported comp -> "-this-package-key"+ | otherwise -> "-package-name"+ , this_arg ]+ | this_arg <- flag ghcOptThisUnitId ] , [ "-hide-all-packages" | flagBool ghcOptHideAllPackages ] , [ "-no-auto-link-packages" | flagBool ghcOptNoAutoLinkPackages ] , packageDbArgs implInfo (ghcOptPackageDBs opts) - , if null (ghcOptSigOf opts)- then []- else "-sig-of"- : intercalate "," (map (\(n,(p,m)) -> display n ++ " is "- ++ display p ++ ":"- ++ display m)- (ghcOptSigOf opts))- : []- , concat $ if flagPackageId implInfo then let space "" = "" space xs = ' ' : xs@@ -419,6 +446,7 @@ where implInfo = getImplInfo comp+ isOSX = os == OSX flag flg = flagToList (flg opts) flags flg = fromNubListR . flg $ opts flagBool flg = fromFlagOrDefault False (flg opts)@@ -430,133 +458,49 @@ | otherwise = ["-w", "-v0"] -packageDbArgs :: GhcImplInfo -> PackageDBStack -> [String]-packageDbArgs implInfo dbstack = case dbstack of+-- | GHC <7.6 uses '-package-conf' instead of '-package-db'.+packageDbArgsConf :: PackageDBStack -> [String]+packageDbArgsConf dbstack = case dbstack of (GlobalPackageDB:UserPackageDB:dbs) -> concatMap specific dbs- (GlobalPackageDB:dbs) -> ("-no-user-" ++ packageDbFlag)+ (GlobalPackageDB:dbs) -> ("-no-user-package-conf") : concatMap specific dbs _ -> ierror where- specific (SpecificPackageDB db) = [ '-':packageDbFlag , db ]- specific _ = ierror- ierror = error $ "internal error: unexpected package db stack: "- ++ show dbstack- packageDbFlag- | flagPackageConf implInfo- = "package-conf"- | otherwise- = "package-db"+ specific (SpecificPackageDB db) = [ "-package-conf", db ]+ specific _ = ierror+ ierror = error $ "internal error: unexpected package db stack: "+ ++ show dbstack +-- | GHC >= 7.6 uses the '-package-db' flag. See+-- https://ghc.haskell.org/trac/ghc/ticket/5977.+packageDbArgsDb :: PackageDBStack -> [String]+-- special cases to make arguments prettier in common scenarios+packageDbArgsDb dbstack = case dbstack of+ (GlobalPackageDB:UserPackageDB:dbs)+ | all isSpecific dbs -> concatMap single dbs+ (GlobalPackageDB:dbs)+ | all isSpecific dbs -> "-no-user-package-db"+ : concatMap single dbs+ dbs -> "-clear-package-db"+ : concatMap single dbs+ where+ single (SpecificPackageDB db) = [ "-package-db", db ]+ single GlobalPackageDB = [ "-global-package-db" ]+ single UserPackageDB = [ "-user-package-db" ]+ isSpecific (SpecificPackageDB _) = True+ isSpecific _ = False +packageDbArgs :: GhcImplInfo -> PackageDBStack -> [String]+packageDbArgs implInfo+ | flagPackageConf implInfo = packageDbArgsConf+ | otherwise = packageDbArgsDb+ -- ----------------------------------------------------------------------------- -- Boilerplate Monoid instance for GhcOptions instance Monoid GhcOptions where- mempty = GhcOptions {- ghcOptMode = mempty,- ghcOptExtra = mempty,- ghcOptExtraDefault = mempty,- ghcOptInputFiles = mempty,- ghcOptInputModules = mempty,- ghcOptOutputFile = mempty,- ghcOptOutputDynFile = mempty,- ghcOptSourcePathClear = mempty,- ghcOptSourcePath = mempty,- ghcOptPackageKey = mempty,- ghcOptPackageDBs = mempty,- ghcOptPackages = mempty,- ghcOptHideAllPackages = mempty,- ghcOptNoAutoLinkPackages = mempty,- ghcOptSigOf = mempty,- ghcOptLinkLibs = mempty,- ghcOptLinkLibPath = mempty,- ghcOptLinkOptions = mempty,- ghcOptLinkFrameworks = mempty,- ghcOptNoLink = mempty,- ghcOptLinkNoHsMain = mempty,- ghcOptCcOptions = mempty,- ghcOptCppOptions = mempty,- ghcOptCppIncludePath = mempty,- ghcOptCppIncludes = mempty,- ghcOptFfiIncludes = mempty,- ghcOptLanguage = mempty,- ghcOptExtensions = mempty,- ghcOptExtensionMap = mempty,- ghcOptOptimisation = mempty,- ghcOptDebugInfo = mempty,- ghcOptProfilingMode = mempty,- ghcOptSplitObjs = mempty,- ghcOptNumJobs = mempty,- ghcOptHPCDir = mempty,- ghcOptGHCiScripts = mempty,- ghcOptHiSuffix = mempty,- ghcOptObjSuffix = mempty,- ghcOptDynHiSuffix = mempty,- ghcOptDynObjSuffix = mempty,- ghcOptHiDir = mempty,- ghcOptObjDir = mempty,- ghcOptOutputDir = mempty,- ghcOptStubDir = mempty,- ghcOptDynLinkMode = mempty,- ghcOptShared = mempty,- ghcOptFPic = mempty,- ghcOptDylibName = mempty,- ghcOptRPaths = mempty,- ghcOptVerbosity = mempty,- ghcOptCabal = mempty- }- mappend a b = GhcOptions {- ghcOptMode = combine ghcOptMode,- ghcOptExtra = combine ghcOptExtra,- ghcOptExtraDefault = combine ghcOptExtraDefault,- ghcOptInputFiles = combine ghcOptInputFiles,- ghcOptInputModules = combine ghcOptInputModules,- ghcOptOutputFile = combine ghcOptOutputFile,- ghcOptOutputDynFile = combine ghcOptOutputDynFile,- ghcOptSourcePathClear = combine ghcOptSourcePathClear,- ghcOptSourcePath = combine ghcOptSourcePath,- ghcOptPackageKey = combine ghcOptPackageKey,- ghcOptPackageDBs = combine ghcOptPackageDBs,- ghcOptPackages = combine ghcOptPackages,- ghcOptHideAllPackages = combine ghcOptHideAllPackages,- ghcOptNoAutoLinkPackages = combine ghcOptNoAutoLinkPackages,- ghcOptSigOf = combine ghcOptSigOf,- ghcOptLinkLibs = combine ghcOptLinkLibs,- ghcOptLinkLibPath = combine ghcOptLinkLibPath,- ghcOptLinkOptions = combine ghcOptLinkOptions,- ghcOptLinkFrameworks = combine ghcOptLinkFrameworks,- ghcOptNoLink = combine ghcOptNoLink,- ghcOptLinkNoHsMain = combine ghcOptLinkNoHsMain,- ghcOptCcOptions = combine ghcOptCcOptions,- ghcOptCppOptions = combine ghcOptCppOptions,- ghcOptCppIncludePath = combine ghcOptCppIncludePath,- ghcOptCppIncludes = combine ghcOptCppIncludes,- ghcOptFfiIncludes = combine ghcOptFfiIncludes,- ghcOptLanguage = combine ghcOptLanguage,- ghcOptExtensions = combine ghcOptExtensions,- ghcOptExtensionMap = combine ghcOptExtensionMap,- ghcOptOptimisation = combine ghcOptOptimisation,- ghcOptDebugInfo = combine ghcOptDebugInfo,- ghcOptProfilingMode = combine ghcOptProfilingMode,- ghcOptSplitObjs = combine ghcOptSplitObjs,- ghcOptNumJobs = combine ghcOptNumJobs,- ghcOptHPCDir = combine ghcOptHPCDir,- ghcOptGHCiScripts = combine ghcOptGHCiScripts,- ghcOptHiSuffix = combine ghcOptHiSuffix,- ghcOptObjSuffix = combine ghcOptObjSuffix,- ghcOptDynHiSuffix = combine ghcOptDynHiSuffix,- ghcOptDynObjSuffix = combine ghcOptDynObjSuffix,- ghcOptHiDir = combine ghcOptHiDir,- ghcOptObjDir = combine ghcOptObjDir,- ghcOptOutputDir = combine ghcOptOutputDir,- ghcOptStubDir = combine ghcOptStubDir,- ghcOptDynLinkMode = combine ghcOptDynLinkMode,- ghcOptShared = combine ghcOptShared,- ghcOptFPic = combine ghcOptFPic,- ghcOptDylibName = combine ghcOptDylibName,- ghcOptRPaths = combine ghcOptRPaths,- ghcOptVerbosity = combine ghcOptVerbosity,- ghcOptCabal = combine ghcOptCabal- }- where- combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>)++instance Semigroup GhcOptions where+ (<>) = gmappend
Distribution/Simple/Program/HcPkg.hs view
@@ -16,53 +16,48 @@ invoke, register, reregister,+ registerMultiInstance, unregister,+ recache, expose, hide, dump,+ describe, list, -- * Program invocations initInvocation, registerInvocation, reregisterInvocation,+ registerMultiInstanceInvocation, unregisterInvocation,+ recacheInvocation, exposeInvocation, hideInvocation, dumpInvocation,+ describeInvocation, listInvocation, ) where -import Prelude hiding (init)-import Distribution.Package- ( PackageId, InstalledPackageId(..) )+import Distribution.Package hiding (installedUnitId) import Distribution.InstalledPackageInfo- ( InstalledPackageInfo, InstalledPackageInfo_(..)- , showInstalledPackageInfo- , emptyInstalledPackageInfo, fieldsInstalledPackageInfo ) import Distribution.ParseUtils import Distribution.Simple.Compiler- ( PackageDB(..), PackageDBStack ) import Distribution.Simple.Program.Types- ( ConfiguredProgram(programId) ) import Distribution.Simple.Program.Run- ( ProgramInvocation(..), IOEncoding(..), programInvocation- , runProgramInvocation, getProgramInvocationOutput ) import Distribution.Text- ( display, simpleParse ) import Distribution.Simple.Utils- ( die ) import Distribution.Verbosity- ( Verbosity, deafening, silent ) import Distribution.Compat.Exception- ( catchExit ) +import Prelude hiding (init) import Data.Char ( isSpace ) import Data.List ( stripPrefix ) import System.FilePath as FilePath- ( (</>), splitPath, splitDirectories, joinPath, isPathSeparator )+ ( (</>), (<.>)+ , splitPath, splitDirectories, joinPath, isPathSeparator ) import qualified System.FilePath.Posix as FilePath.Posix -- | Information about the features and capabilities of an @hc-pkg@@@ -73,17 +68,25 @@ , noPkgDbStack :: Bool -- ^ no package DB stack supported , noVerboseFlag :: Bool -- ^ hc-pkg does not support verbosity flags , flagPackageConf :: Bool -- ^ use package-conf option instead of package-db- , useSingleFileDb :: Bool -- ^ requires single file package database+ , supportsDirDbs :: Bool -- ^ supports directory style package databases+ , requiresDirDbs :: Bool -- ^ requires directory style package databases+ , nativeMultiInstance :: Bool -- ^ supports --enable-multi-instance flag+ , recacheMultiInstance :: Bool -- ^ supports multi-instance via recache } -- | Call @hc-pkg@ to initialise a package database at the location {path}. -- -- > hc-pkg init {path} ---init :: HcPkgInfo -> Verbosity -> FilePath -> IO ()-init hpi verbosity path =- runProgramInvocation verbosity (initInvocation hpi verbosity path)+init :: HcPkgInfo -> Verbosity -> Bool -> FilePath -> IO ()+init hpi verbosity preferCompat path+ | not (supportsDirDbs hpi)+ || (not (requiresDirDbs hpi) && preferCompat)+ = writeFile path "[]" + | otherwise+ = runProgramInvocation verbosity (initInvocation hpi verbosity path)+ -- | Run @hc-pkg@ using a given package DB stack, directly forwarding the -- provided command-line arguments to it. invoke :: HcPkgInfo -> Verbosity -> PackageDBStack -> [String] -> IO ()@@ -118,7 +121,51 @@ runProgramInvocation verbosity (reregisterInvocation hpi verbosity packagedb pkgFile) +registerMultiInstance :: HcPkgInfo -> Verbosity+ -> PackageDBStack+ -> InstalledPackageInfo+ -> IO ()+registerMultiInstance hpi verbosity packagedbs pkgInfo+ | nativeMultiInstance hpi+ = runProgramInvocation verbosity+ (registerMultiInstanceInvocation hpi verbosity packagedbs (Right pkgInfo)) + -- This is a trick. Older versions of GHC do not support the+ -- --enable-multi-instance flag for ghc-pkg register but it turns out that+ -- the same ability is available by using ghc-pkg recache. The recache+ -- command is there to support distro package managers that like to work+ -- by just installing files and running update commands, rather than+ -- special add/remove commands. So the way to register by this method is+ -- to write the package registration file directly into the package db and+ -- then call hc-pkg recache.+ --+ | recacheMultiInstance hpi+ = do let pkgdb = last packagedbs+ writeRegistrationFileDirectly hpi pkgdb pkgInfo+ recache hpi verbosity pkgdb++ | otherwise+ = die $ "HcPkg.registerMultiInstance: the compiler does not support "+ ++ "registering multiple instances of packages."++writeRegistrationFileDirectly :: HcPkgInfo+ -> PackageDB+ -> InstalledPackageInfo+ -> IO ()+writeRegistrationFileDirectly hpi (SpecificPackageDB dir) pkgInfo+ | supportsDirDbs hpi+ = do let pkgfile = dir </> display (installedUnitId pkgInfo) <.> "conf"+ writeUTF8File pkgfile (showInstalledPackageInfo pkgInfo)++ | otherwise+ = die $ "HcPkg.writeRegistrationFileDirectly: compiler does not support dir style package dbs"++writeRegistrationFileDirectly _ _ _ =+ -- We don't know here what the dir for the global or user dbs are,+ -- if that's needed it'll require a bit more plumbing to support.+ die $ "HcPkg.writeRegistrationFileDirectly: only supports SpecificPackageDB for now"++ -- | Call @hc-pkg@ to unregister a package -- -- > hc-pkg unregister [pkgid] [--user | --global | --package-db]@@ -129,6 +176,16 @@ (unregisterInvocation hpi verbosity packagedb pkgid) +-- | Call @hc-pkg@ to recache the registered packages.+--+-- > hc-pkg recache [--user | --global | --package-db]+--+recache :: HcPkgInfo -> Verbosity -> PackageDB -> IO ()+recache hpi verbosity packagedb =+ runProgramInvocation verbosity+ (recacheInvocation hpi verbosity packagedb)++ -- | Call @hc-pkg@ to expose a package. -- -- > hc-pkg expose [pkgid] [--user | --global | --package-db]@@ -138,7 +195,22 @@ runProgramInvocation verbosity (exposeInvocation hpi verbosity packagedb pkgid) +-- | Call @hc-pkg@ to retrieve a specific package+--+-- > hc-pkg describe [pkgid] [--user | --global | --package-db]+--+describe :: HcPkgInfo -> Verbosity -> PackageDBStack -> PackageId -> IO [InstalledPackageInfo]+describe hpi verbosity packagedb pid = do + output <- getProgramInvocationOutput verbosity+ (describeInvocation hpi verbosity packagedb pid)+ `catchIO` \_ -> return ""++ case parsePackages output of+ Left ok -> return ok+ _ -> die $ "failed to parse output of '"+ ++ programId (hcPkgProgram hpi) ++ " describe " ++ display pid ++ "'"+ -- | Call @hc-pkg@ to hide a package. -- -- > hc-pkg hide [pkgid] [--user | --global | --package-db]@@ -157,40 +229,40 @@ output <- getProgramInvocationOutput verbosity (dumpInvocation hpi verbosity packagedb)- `catchExit` \_ -> die $ programId (hcPkgProgram hpi) ++ " dump failed"+ `catchIO` \_ -> die $ programId (hcPkgProgram hpi) ++ " dump failed" case parsePackages output of Left ok -> return ok _ -> die $ "failed to parse output of '" ++ programId (hcPkgProgram hpi) ++ " dump'" +parsePackages :: String -> Either [InstalledPackageInfo] [PError]+parsePackages str =+ let parsed = map parseInstalledPackageInfo' (splitPkgs str)+ in case [ msg | ParseFailed msg <- parsed ] of+ [] -> Left [ setUnitId+ . maybe id mungePackagePaths (pkgRoot pkg)+ $ pkg+ | ParseOk _ pkg <- parsed ]+ msgs -> Right msgs where- parsePackages str =- let parsed = map parseInstalledPackageInfo' (splitPkgs str)- in case [ msg | ParseFailed msg <- parsed ] of- [] -> Left [ setInstalledPackageId- . maybe id mungePackagePaths (pkgRoot pkg)- $ pkg- | ParseOk _ pkg <- parsed ]- msgs -> Right msgs- parseInstalledPackageInfo' = parseFieldsFlat fieldsInstalledPackageInfo emptyInstalledPackageInfo - --TODO: this could be a lot faster. We're doing normaliseLineEndings twice- -- and converting back and forth with lines/unlines.- splitPkgs :: String -> [String]- splitPkgs = checkEmpty . map unlines . splitWith ("---" ==) . lines- where- -- Handle the case of there being no packages at all.- checkEmpty [s] | all isSpace s = []- checkEmpty ss = ss+--TODO: this could be a lot faster. We're doing normaliseLineEndings twice+-- and converting back and forth with lines/unlines.+splitPkgs :: String -> [String]+splitPkgs = checkEmpty . map unlines . splitWith ("---" ==) . lines+ where+ -- Handle the case of there being no packages at all.+ checkEmpty [s] | all isSpace s = []+ checkEmpty ss = ss - splitWith :: (a -> Bool) -> [a] -> [[a]]- splitWith p xs = ys : case zs of- [] -> []- _:ws -> splitWith p ws- where (ys,zs) = break p xs+ splitWith :: (a -> Bool) -> [a] -> [[a]]+ splitWith p xs = ys : case zs of+ [] -> []+ _:ws -> splitWith p ws+ where (ys,zs) = break p xs mungePackagePaths :: FilePath -> InstalledPackageInfo -> InstalledPackageInfo -- Perform path/URL variable substitution as per the Cabal ${pkgroot} spec@@ -230,26 +302,24 @@ _ -> Nothing --- Older installed package info files did not have the installedPackageId+-- Older installed package info files did not have the installedUnitId -- field, so if it is missing then we fill it as the source package ID.-setInstalledPackageId :: InstalledPackageInfo -> InstalledPackageInfo-setInstalledPackageId pkginfo@InstalledPackageInfo {- installedPackageId = InstalledPackageId "",- sourcePackageId = pkgid+setUnitId :: InstalledPackageInfo -> InstalledPackageInfo+setUnitId pkginfo@InstalledPackageInfo {+ installedUnitId = SimpleUnitId (ComponentId ""),+ sourcePackageId = pkgid } = pkginfo {- --TODO use a proper named function for the conversion- -- from source package id to installed package id- installedPackageId = InstalledPackageId (display pkgid)+ installedUnitId = mkLegacyUnitId pkgid }-setInstalledPackageId pkginfo = pkginfo+setUnitId pkginfo = pkginfo -- | Call @hc-pkg@ to get the source package Id of all the packages in the -- given package database. -- -- This is much less information than with 'dump', but also rather quicker.--- Note in particular that it does not include the 'InstalledPackageId', just+-- Note in particular that it does not include the 'UnitId', just -- the source 'PackageId' which is not necessarily unique in any package db. -- list :: HcPkgInfo -> Verbosity -> PackageDB@@ -258,7 +328,7 @@ output <- getProgramInvocationOutput verbosity (listInvocation hpi verbosity packagedb)- `catchExit` \_ -> die $ programId (hcPkgProgram hpi) ++ " list failed"+ `catchIO` \_ -> die $ programId (hcPkgProgram hpi) ++ " list failed" case parsePackageIds output of Just ok -> return ok@@ -279,38 +349,36 @@ args = ["init", path] ++ verbosityOpts hpi verbosity -registerInvocation, reregisterInvocation+registerInvocation, reregisterInvocation, registerMultiInstanceInvocation :: HcPkgInfo -> Verbosity -> PackageDBStack -> Either FilePath InstalledPackageInfo -> ProgramInvocation-registerInvocation = registerInvocation' "register"-reregisterInvocation = registerInvocation' "update"-+registerInvocation = registerInvocation' "register" False+reregisterInvocation = registerInvocation' "update" False+registerMultiInstanceInvocation = registerInvocation' "update" True -registerInvocation' :: String -> HcPkgInfo -> Verbosity -> PackageDBStack+registerInvocation' :: String -> Bool+ -> HcPkgInfo -> Verbosity -> PackageDBStack -> Either FilePath InstalledPackageInfo -> ProgramInvocation-registerInvocation' cmdname hpi verbosity packagedbs (Left pkgFile) =- programInvocation (hcPkgProgram hpi) args- where- args = [cmdname, pkgFile]- ++ (if noPkgDbStack hpi- then [packageDbOpts hpi (last packagedbs)]- else packageDbStackOpts hpi packagedbs)- ++ verbosityOpts hpi verbosity+registerInvocation' cmdname multiInstance hpi+ verbosity packagedbs pkgFileOrInfo =+ case pkgFileOrInfo of+ Left pkgFile ->+ programInvocation (hcPkgProgram hpi) (args pkgFile) -registerInvocation' cmdname hpi verbosity packagedbs (Right pkgInfo) =- (programInvocation (hcPkgProgram hpi) args) {- progInvokeInput = Just (showInstalledPackageInfo pkgInfo),- progInvokeInputEncoding = IOEncodingUTF8- }+ Right pkgInfo ->+ (programInvocation (hcPkgProgram hpi) (args "-")) {+ progInvokeInput = Just (showInstalledPackageInfo pkgInfo),+ progInvokeInputEncoding = IOEncodingUTF8+ } where- args = [cmdname, "-"]- ++ (if noPkgDbStack hpi- then [packageDbOpts hpi (last packagedbs)]- else packageDbStackOpts hpi packagedbs)- ++ verbosityOpts hpi verbosity-+ args file = [cmdname, file]+ ++ (if noPkgDbStack hpi+ then [packageDbOpts hpi (last packagedbs)]+ else packageDbStackOpts hpi packagedbs)+ ++ [ "--enable-multi-instance" | multiInstance ]+ ++ verbosityOpts hpi verbosity unregisterInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId -> ProgramInvocation@@ -320,6 +388,14 @@ ++ verbosityOpts hpi verbosity +recacheInvocation :: HcPkgInfo -> Verbosity -> PackageDB+ -> ProgramInvocation+recacheInvocation hpi verbosity packagedb =+ programInvocation (hcPkgProgram hpi) $+ ["recache", packageDbOpts hpi packagedb]+ ++ verbosityOpts hpi verbosity++ exposeInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId -> ProgramInvocation exposeInvocation hpi verbosity packagedb pkgid =@@ -327,6 +403,15 @@ ["expose", packageDbOpts hpi packagedb, display pkgid] ++ verbosityOpts hpi verbosity +describeInvocation :: HcPkgInfo -> Verbosity -> PackageDBStack -> PackageId+ -> ProgramInvocation+describeInvocation hpi verbosity packagedbs pkgid =+ programInvocation (hcPkgProgram hpi) $+ ["describe", display pkgid]+ ++ (if noPkgDbStack hpi+ then [packageDbOpts hpi (last packagedbs)]+ else packageDbStackOpts hpi packagedbs)+ ++ verbosityOpts hpi verbosity hideInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId -> ProgramInvocation
Distribution/Simple/Program/Hpc.hs view
@@ -13,14 +13,13 @@ , union ) where -import Distribution.ModuleName ( ModuleName )+import Distribution.ModuleName import Distribution.Simple.Program.Run- ( ProgramInvocation, programInvocation, runProgramInvocation )-import Distribution.Simple.Program.Types ( ConfiguredProgram(..) )-import Distribution.Text ( display )-import Distribution.Simple.Utils ( warn )-import Distribution.Verbosity ( Verbosity )-import Distribution.Version ( Version(..), orLaterVersion, withinRange )+import Distribution.Simple.Program.Types+import Distribution.Text+import Distribution.Simple.Utils+import Distribution.Verbosity+import Distribution.Version -- | Invoke hpc with the given parameters. --
+ Distribution/Simple/Program/Internal.hs view
@@ -0,0 +1,46 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Internal+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Internal utilities used by Distribution.Simple.Program.*.++module Distribution.Simple.Program.Internal (+ stripExtractVersion,+ ) where++import Data.Char (isDigit)+import Data.List (isPrefixOf, isSuffixOf)++-- | Extract the version number from the output of 'strip --version'.+--+-- Invoking "strip --version" gives very inconsistent results. We ignore+-- everything in parentheses (see #2497), look for the first word that starts+-- with a number, and try parsing out the first two components of it. Non-GNU+-- 'strip' doesn't appear to have a version flag.+stripExtractVersion :: String -> String+stripExtractVersion str =+ let numeric "" = False+ numeric (x:_) = isDigit x++ -- Filter out everything in parentheses.+ filterPar' :: Int -> [String] -> [String]+ filterPar' _ [] = []+ filterPar' n (x:xs)+ | n >= 0 && "(" `isPrefixOf` x = filterPar' (n+1) ((tail x):xs)+ | n > 0 && ")" `isSuffixOf` x = filterPar' (n-1) xs+ | n > 0 = filterPar' n xs+ | otherwise = x:filterPar' n xs++ filterPar = filterPar' 0++ in case dropWhile (not . numeric) (filterPar . words $ str) of+ (ver:_) ->+ -- take the first two version components+ let isDot = (== '.')+ (major, rest) = break isDot ver+ minor = takeWhile isDigit (dropWhile isDot rest)+ in major ++ "." ++ minor+ _ -> ""
Distribution/Simple/Program/Run.hs view
@@ -24,12 +24,9 @@ ) where import Distribution.Simple.Program.Types- ( ConfiguredProgram(..), programPath ) import Distribution.Simple.Utils- ( die, rawSystemExit, rawSystemIOWithEnv, rawSystemStdInOut- , toUTF8, fromUTF8, normaliseLineEndings ) import Distribution.Verbosity- ( Verbosity )+import Distribution.Compat.Environment import Data.List ( foldl', unfoldr )@@ -38,8 +35,6 @@ ( when ) import System.Exit ( ExitCode(..), exitWith )-import Distribution.Compat.Environment- ( getEnvironment ) -- | Represents a specific invocation of a specific program. --
Distribution/Simple/Program/Script.hs view
@@ -17,9 +17,7 @@ ) where import Distribution.Simple.Program.Run- ( ProgramInvocation(..) ) import Distribution.System- ( OS(..) ) import Data.Maybe ( maybeToList )
Distribution/Simple/Program/Strip.hs view
@@ -10,16 +10,13 @@ module Distribution.Simple.Program.Strip (stripLib, stripExe) where -import Distribution.Simple.Program (ProgramConfiguration, lookupProgram- , programVersion, rawSystemProgram- , stripProgram)-import Distribution.Simple.Utils (warn)-import Distribution.System (Arch(..), Platform(..), OS (..), buildOS)-import Distribution.Verbosity (Verbosity)-import Distribution.Version (orLaterVersion, withinRange)+import Distribution.Simple.Program+import Distribution.Simple.Utils+import Distribution.System+import Distribution.Verbosity+import Distribution.Version import Control.Monad (unless)-import Data.Version (Version(..)) import System.FilePath (takeBaseName) runStrip :: Verbosity -> ProgramConfiguration -> FilePath -> [String] -> IO ()@@ -47,10 +44,11 @@ stripLib :: Verbosity -> Platform -> ProgramConfiguration -> FilePath -> IO () stripLib verbosity (Platform arch os) conf path = do case os of- OSX -> -- '--strip-unneeded' is not supported on OS X, iOS or+ OSX -> -- '--strip-unneeded' is not supported on OS X, iOS, AIX, or -- Solaris. See #1630. return () IOS -> return ()+ AIX -> return () Solaris -> return () Windows -> -- Stripping triggers a bug in 'strip.exe' for -- libraries with lots identically named modules. See
Distribution/Simple/Program/Types.hs view
@@ -33,14 +33,10 @@ ) where import Distribution.Simple.Program.Find- ( ProgramSearchPath, ProgramSearchPathEntry(..)- , findProgramOnSearchPath ) import Distribution.Version- ( Version ) import Distribution.Verbosity- ( Verbosity )+import Distribution.Compat.Binary -import Distribution.Compat.Binary (Binary) import qualified Data.Map as Map import GHC.Generics (Generic) @@ -59,8 +55,13 @@ -- -- It is supplied with the prevailing search path which will typically -- just be used as-is, but can be extended or ignored as needed.+ --+ -- For the purpose of change monitoring, in addition to the location+ -- where the program was found, it returns all the other places that+ -- were tried.+ -- programFindLocation :: Verbosity -> ProgramSearchPath- -> IO (Maybe FilePath),+ -> IO (Maybe (FilePath, [FilePath])), -- | Try to find the version of the program. For many programs this is -- not possible or is not necessary so it's OK to return Nothing.@@ -108,9 +109,18 @@ programProperties :: Map.Map String String, -- | Location of the program. eg. @\/usr\/bin\/ghc-6.4@- programLocation :: ProgramLocation- } deriving (Eq, Generic, Read, Show)+ programLocation :: ProgramLocation, + -- | In addition to the 'programLocation' where the program was found,+ -- these are additional locations that were looked at. The combination+ -- of ths found location and these not-found locations can be used to+ -- monitor to detect when the re-configuring the program might give a+ -- different result (e.g. found in a different location).+ --+ programMonitorFiles :: [FilePath]+ }+ deriving (Eq, Generic, Read, Show)+ instance Binary ConfiguredProgram -- | Where a program was found. Also tells us whether it's specified by user or@@ -160,5 +170,6 @@ programOverrideArgs = [], programOverrideEnv = [], programProperties = Map.empty,- programLocation = loc+ programLocation = loc,+ programMonitorFiles = [] -- did not look in any other locations }
Distribution/Simple/Register.hs view
@@ -28,6 +28,10 @@ unregister, initPackageDB,+ doesPackageDBExist,+ createPackageDB,+ deletePackageDB,+ invokeHcPkg, registerPackage, generateRegistrationInfo,@@ -37,11 +41,7 @@ ) where import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), ComponentLocalBuildInfo(..)- , ComponentName(..), getComponentLocalBuildInfo- , LibraryName(..)- , InstallDirs(..), absoluteInstallDirs )-import Distribution.Simple.BuildPaths (haddockName)+import Distribution.Simple.BuildPaths import qualified Distribution.Simple.GHC as GHC import qualified Distribution.Simple.GHCJS as GHCJS@@ -50,41 +50,25 @@ import qualified Distribution.Simple.HaskellSuite as HaskellSuite import Distribution.Simple.Compiler- ( compilerVersion, Compiler, CompilerFlavor(..), compilerFlavor- , PackageDB, PackageDBStack, absolutePackageDBPaths- , registrationPackageDB ) import Distribution.Simple.Program- ( ProgramConfiguration, runProgramInvocation ) import Distribution.Simple.Program.Script- ( invocationAsSystemScript )-import Distribution.Simple.Program.HcPkg (HcPkgInfo) import qualified Distribution.Simple.Program.HcPkg as HcPkg import Distribution.Simple.Setup- ( RegisterFlags(..), CopyDest(..)- , fromFlag, fromFlagOrDefault, flagToMaybe ) import Distribution.PackageDescription- ( PackageDescription(..), Library(..), BuildInfo(..), libModules ) import Distribution.Package- ( Package(..), packageName, InstalledPackageId(..) )-import Distribution.InstalledPackageInfo- ( InstalledPackageInfo, InstalledPackageInfo_(InstalledPackageInfo)- , showInstalledPackageInfo ) import qualified Distribution.InstalledPackageInfo as IPI+import Distribution.InstalledPackageInfo (InstalledPackageInfo) import Distribution.Simple.Utils- ( writeUTF8File, writeFileAtomic, setFileExecutable- , die, notice, setupMessage, shortRelativePath ) import Distribution.System- ( OS(..), buildOS ) import Distribution.Text- ( display )-import Distribution.Version ( Version(..) ) import Distribution.Verbosity as Verbosity- ( Verbosity, normal ) import System.FilePath ((</>), (<.>), isAbsolute) import System.Directory- ( getCurrentDirectory )+ ( getCurrentDirectory, removeDirectoryRecursive, removeFile+ , doesDirectoryExist, doesFileExist ) +import Data.Version import Control.Monad (when) import Data.Maybe ( isJust, fromMaybe, maybeToList )@@ -108,14 +92,16 @@ (registrationPackageDB absPackageDBs) when (fromFlag (regPrintId regFlags)) $ do- putStrLn (display (IPI.installedPackageId installedPkgInfo))+ putStrLn (display (IPI.installedUnitId installedPkgInfo)) -- Three different modes: case () of _ | modeGenerateRegFile -> writeRegistrationFile installedPkgInfo | modeGenerateRegScript -> writeRegisterScript installedPkgInfo- | otherwise -> registerPackage verbosity- installedPkgInfo pkg lbi inplace packageDbs+ | otherwise -> do+ setupMessage verbosity "Registering" (packageId pkg)+ registerPackage verbosity (compiler lbi) (withPrograms lbi) False+ packageDbs installedPkgInfo where modeGenerateRegFile = isJust (flagToMaybe (regGenPkgConf regFlags))@@ -136,7 +122,7 @@ writeRegistrationFile installedPkgInfo = do notice verbosity ("Creating package registration file: " ++ regFile)- writeUTF8File regFile (showInstalledPackageInfo installedPkgInfo)+ writeUTF8File regFile (IPI.showInstalledPackageInfo installedPkgInfo) writeRegisterScript installedPkgInfo = case compilerFlavor (compiler lbi) of@@ -166,59 +152,80 @@ --TODO: eliminate pwd! pwd <- getCurrentDirectory - --TODO: the method of setting the InstalledPackageId is compiler specific+ --TODO: the method of setting the UnitId is compiler specific -- this aspect should be delegated to a per-compiler helper. let comp = compiler lbi- ipid <-+ abi_hash <- case compilerFlavor comp of GHC | compilerVersion comp >= Version [6,11] [] -> do- s <- GHC.libAbiHash verbosity pkg lbi lib clbi- return (InstalledPackageId (display (packageId pkg) ++ '-':s))+ fmap AbiHash $ GHC.libAbiHash verbosity pkg lbi lib clbi GHCJS -> do- s <- GHCJS.libAbiHash verbosity pkg lbi lib clbi- return (InstalledPackageId (display (packageId pkg) ++ '-':s))- _other -> do- return (InstalledPackageId (display (packageId pkg)))+ fmap AbiHash $ GHCJS.libAbiHash verbosity pkg lbi lib clbi+ _ -> return (AbiHash "") installedPkgInfo <- if inplace then return (inplaceInstalledPackageInfo pwd distPref- pkg ipid lib lbi clbi)+ pkg abi_hash lib lbi clbi) else if reloc then relocRegistrationInfo verbosity- pkg lib lbi clbi ipid packageDb+ pkg lib lbi clbi abi_hash packageDb else return (absoluteInstalledPackageInfo- pkg ipid lib lbi clbi)+ pkg abi_hash lib lbi clbi) - return installedPkgInfo{ IPI.installedPackageId = ipid }+ return installedPkgInfo{ IPI.abiHash = abi_hash } relocRegistrationInfo :: Verbosity -> PackageDescription -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo- -> InstalledPackageId+ -> AbiHash -> PackageDB -> IO InstalledPackageInfo-relocRegistrationInfo verbosity pkg lib lbi clbi ipid packageDb =+relocRegistrationInfo verbosity pkg lib lbi clbi abi_hash packageDb = case (compilerFlavor (compiler lbi)) of GHC -> do fs <- GHC.pkgRoot verbosity lbi packageDb return (relocatableInstalledPackageInfo- pkg ipid lib lbi clbi fs)+ pkg abi_hash lib lbi clbi fs) _ -> die "Distribution.Simple.Register.relocRegistrationInfo: \ \not implemented for this compiler" +initPackageDB :: Verbosity -> Compiler -> ProgramConfiguration -> FilePath -> IO ()+initPackageDB verbosity comp progdb dbPath =+ createPackageDB verbosity comp progdb False dbPath+ -- | Create an empty package DB at the specified location.-initPackageDB :: Verbosity -> Compiler -> ProgramConfiguration -> FilePath- -> IO ()-initPackageDB verbosity comp conf dbPath =- case compilerFlavor comp of- HaskellSuite {} -> HaskellSuite.initPackageDB verbosity conf dbPath- _ -> withHcPkg "Distribution.Simple.Register.initPackageDB: \- \not implemented for this compiler" comp conf- (\hpi -> HcPkg.init hpi verbosity dbPath)+createPackageDB :: Verbosity -> Compiler -> ProgramConfiguration -> Bool+ -> FilePath -> IO ()+createPackageDB verbosity comp progdb preferCompat dbPath =+ case compilerFlavor comp of+ GHC -> HcPkg.init (GHC.hcPkgInfo progdb) verbosity preferCompat dbPath+ GHCJS -> HcPkg.init (GHCJS.hcPkgInfo progdb) verbosity False dbPath+ LHC -> HcPkg.init (LHC.hcPkgInfo progdb) verbosity False dbPath+ UHC -> return ()+ HaskellSuite _ -> HaskellSuite.initPackageDB verbosity progdb dbPath+ _ -> die $ "Distribution.Simple.Register.createPackageDB: "+ ++ "not implemented for this compiler" +doesPackageDBExist :: FilePath -> IO Bool+doesPackageDBExist dbPath = do+ -- currently one impl for all compiler flavours, but could change if needed+ dir_exists <- doesDirectoryExist dbPath+ if dir_exists+ then return True+ else doesFileExist dbPath++deletePackageDB :: FilePath -> IO ()+deletePackageDB dbPath = do+ -- currently one impl for all compiler flavours, but could change if needed+ dir_exists <- doesDirectoryExist dbPath+ if dir_exists+ then removeDirectoryRecursive dbPath+ else do file_exists <- doesFileExist dbPath+ when file_exists $ removeFile dbPath+ -- | Run @hc-pkg@ using a given package DB stack, directly forwarding the -- provided command-line arguments to it. invokeHcPkg :: Verbosity -> Compiler -> ProgramConfiguration -> PackageDBStack@@ -228,7 +235,7 @@ (\hpi -> HcPkg.invoke hpi verbosity dbStack extraArgs) withHcPkg :: String -> Compiler -> ProgramConfiguration- -> (HcPkgInfo -> IO a) -> IO a+ -> (HcPkg.HcPkgInfo -> IO a) -> IO a withHcPkg name comp conf f = case compilerFlavor comp of GHC -> f (GHC.hcPkgInfo conf)@@ -238,31 +245,29 @@ \not implemented for this compiler") registerPackage :: Verbosity- -> InstalledPackageInfo- -> PackageDescription- -> LocalBuildInfo+ -> Compiler+ -> ProgramConfiguration -> Bool -> PackageDBStack+ -> InstalledPackageInfo -> IO ()-registerPackage verbosity installedPkgInfo pkg lbi inplace packageDbs = do- let msg = if inplace- then "In-place registering"- else "Registering"- setupMessage verbosity msg (packageId pkg)- case compilerFlavor (compiler lbi) of- GHC -> GHC.registerPackage verbosity installedPkgInfo pkg lbi inplace packageDbs- GHCJS -> GHCJS.registerPackage verbosity installedPkgInfo pkg lbi inplace packageDbs- LHC -> LHC.registerPackage verbosity installedPkgInfo pkg lbi inplace packageDbs- UHC -> UHC.registerPackage verbosity installedPkgInfo pkg lbi inplace packageDbs+registerPackage verbosity comp progdb multiInstance packageDbs installedPkgInfo =+ case compilerFlavor comp of+ GHC -> GHC.registerPackage verbosity progdb multiInstance packageDbs installedPkgInfo+ GHCJS -> GHCJS.registerPackage verbosity progdb multiInstance packageDbs installedPkgInfo+ _ | multiInstance+ -> die "Registering multiple package instances is not yet supported for this compiler"+ LHC -> LHC.registerPackage verbosity progdb packageDbs installedPkgInfo+ UHC -> UHC.registerPackage verbosity comp progdb packageDbs installedPkgInfo JHC -> notice verbosity "Registering for jhc (nothing to do)" HaskellSuite {} ->- HaskellSuite.registerPackage verbosity installedPkgInfo pkg lbi inplace packageDbs+ HaskellSuite.registerPackage verbosity progdb packageDbs installedPkgInfo _ -> die "Registering is not implemented for this compiler" writeHcPkgRegisterScript :: Verbosity -> InstalledPackageInfo -> PackageDBStack- -> HcPkgInfo+ -> HcPkg.HcPkgInfo -> IO () writeHcPkgRegisterScript verbosity installedPkgInfo packageDbs hpi = do let invocation = HcPkg.reregisterInvocation hpi Verbosity.normal@@ -289,17 +294,17 @@ :: ([FilePath] -> [FilePath]) -- ^ Translate relative include dir paths to -- absolute paths. -> PackageDescription- -> InstalledPackageId+ -> AbiHash -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo -> InstallDirs FilePath -> InstalledPackageInfo-generalInstalledPackageInfo adjustRelIncDirs pkg ipid lib lbi clbi installDirs =- InstalledPackageInfo {- IPI.installedPackageId = ipid,+generalInstalledPackageInfo adjustRelIncDirs pkg abi_hash lib lbi clbi installDirs =+ IPI.InstalledPackageInfo { IPI.sourcePackageId = packageId pkg,- IPI.packageKey = pkgKey lbi,+ IPI.installedUnitId = componentUnitId clbi,+ IPI.compatPackageKey = componentCompatPackageKey clbi, IPI.license = license pkg, IPI.copyright = copyright pkg, IPI.maintainer = maintainer pkg,@@ -310,12 +315,10 @@ IPI.synopsis = synopsis pkg, IPI.description = description pkg, IPI.category = category pkg,+ IPI.abiHash = abi_hash, IPI.exposed = libExposed lib,- IPI.exposedModules = map fixupSelf (componentExposedModules clbi),+ IPI.exposedModules = componentExposedModules clbi, IPI.hiddenModules = otherModules bi,- IPI.instantiatedWith = map (\(k,(p,n)) ->- (k,IPI.OriginalModule (IPI.installedPackageId p) n))- (instantiatedWith lbi), IPI.trusted = IPI.trusted IPI.emptyInstalledPackageInfo, IPI.importDirs = [ libdir installDirs | hasModules ], -- Note. the libsubdir and datasubdir templates have already been expanded@@ -324,9 +327,9 @@ then libdir installDirs : extraLibDirs bi else extraLibDirs bi, IPI.dataDir = datadir installDirs,- IPI.hsLibraries = [ libname- | LibraryName libname <- componentLibraries clbi- , hasLibrary ],+ IPI.hsLibraries = if hasLibrary+ then [getHSLibraryName (componentUnitId clbi)]+ else [], IPI.extraLibraries = extraLibs bi, IPI.extraGHCiLibraries = extraGHCiLibs bi, IPI.includeDirs = absinc ++ adjustRelIncDirs relinc,@@ -336,8 +339,8 @@ -- We don't want cc-options to be propagated -- to C compilations in other packages. IPI.ldOptions = ldOptions bi,- IPI.frameworkDirs = [], IPI.frameworks = frameworks bi,+ IPI.frameworkDirs = extraFrameworkDirs bi, IPI.haddockInterfaces = [haddockdir installDirs </> haddockName pkg], IPI.haddockHTMLs = [htmldir installDirs], IPI.pkgRoot = Nothing@@ -350,18 +353,6 @@ || (not (null (jsSources bi)) && compilerFlavor (compiler lbi) == GHCJS) - -- Since we currently don't decide the InstalledPackageId of our package- -- until just before we register, we didn't have one for the re-exports- -- of modules defined within this package, so we used an empty one that- -- we fill in here now that we know what it is. It's a bit of a hack,- -- we ought really to decide the InstalledPackageId ahead of time.- fixupSelf (IPI.ExposedModule n o o') =- IPI.ExposedModule n (fmap fixupOriginalModule o)- (fmap fixupOriginalModule o')- fixupOriginalModule (IPI.OriginalModule i m) = IPI.OriginalModule (fixupIpid i) m- fixupIpid (InstalledPackageId []) = ipid- fixupIpid x = x- -- | Construct 'InstalledPackageInfo' for a library that is in place in the -- build tree. --@@ -370,19 +361,22 @@ inplaceInstalledPackageInfo :: FilePath -- ^ top of the build tree -> FilePath -- ^ location of the dist tree -> PackageDescription- -> InstalledPackageId+ -> AbiHash -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo -> InstalledPackageInfo-inplaceInstalledPackageInfo inplaceDir distPref pkg ipid lib lbi clbi =+inplaceInstalledPackageInfo inplaceDir distPref pkg abi_hash lib lbi clbi = generalInstalledPackageInfo adjustRelativeIncludeDirs- pkg ipid lib lbi clbi installDirs+ pkg abi_hash lib lbi clbi installDirs where adjustRelativeIncludeDirs = map (inplaceDir </>)+ libTargetDir+ | componentUnitId clbi == localUnitId lbi = buildDir lbi+ | otherwise = buildDir lbi </> display (componentUnitId clbi) installDirs = (absoluteInstallDirs pkg lbi NoCopyDest) {- libdir = inplaceDir </> buildDir lbi,+ libdir = inplaceDir </> libTargetDir, datadir = inplaceDir </> dataDir pkg, docdir = inplaceDocdir, htmldir = inplaceHtmldir,@@ -398,14 +392,14 @@ -- This function knows about the layout of installed packages. -- absoluteInstalledPackageInfo :: PackageDescription- -> InstalledPackageId+ -> AbiHash -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo -> InstalledPackageInfo-absoluteInstalledPackageInfo pkg ipid lib lbi clbi =+absoluteInstalledPackageInfo pkg abi_hash lib lbi clbi = generalInstalledPackageInfo adjustReativeIncludeDirs- pkg ipid lib lbi clbi installDirs+ pkg abi_hash lib lbi clbi installDirs where -- For installed packages we install all include files into one dir, -- whereas in the build tree they may live in multiple local dirs.@@ -417,15 +411,15 @@ relocatableInstalledPackageInfo :: PackageDescription- -> InstalledPackageId+ -> AbiHash -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo -> FilePath -> InstalledPackageInfo-relocatableInstalledPackageInfo pkg ipid lib lbi clbi pkgroot =+relocatableInstalledPackageInfo pkg abi_hash lib lbi clbi pkgroot = generalInstalledPackageInfo adjustReativeIncludeDirs- pkg ipid lib lbi clbi installDirs+ pkg abi_hash lib lbi clbi installDirs where -- For installed packages we install all include files into one dir, -- whereas in the build tree they may live in multiple local dirs.
Distribution/Simple/Setup.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveGeneric #-} -----------------------------------------------------------------------------@@ -30,12 +30,12 @@ -- read and written from files. This would allow us to save configure flags in -- config files. -{-# LANGUAGE CPP #-}- module Distribution.Simple.Setup ( GlobalFlags(..), emptyGlobalFlags, defaultGlobalFlags, globalCommand, ConfigFlags(..), emptyConfigFlags, defaultConfigFlags, configureCommand,+ configPrograms,+ AllowNewer(..), AllowNewerDep(..), isAllowNewer, configAbsolutePaths, readPackageDbList, showPackageDbList, CopyFlags(..), emptyCopyFlags, defaultCopyFlags, copyCommand, InstallFlags(..), emptyInstallFlags, defaultInstallFlags, installCommand,@@ -56,8 +56,9 @@ configureArgs, configureOptions, configureCCompiler, configureLinker, buildOptions, haddockOptions, installDirsOptions, programConfigurationOptions, programConfigurationPaths',+ splitArgs, - defaultDistPref,+ defaultDistPref, optionDistPref, Flag(..), toFlag,@@ -65,50 +66,34 @@ fromFlagOrDefault, flagToMaybe, flagToList,- boolOpt, boolOpt', trueArg, falseArg, optionVerbosity, optionNumJobs ) where+ boolOpt, boolOpt', trueArg, falseArg,+ optionVerbosity, optionNumJobs, readPToMaybe ) where -import Distribution.Compiler ()+import Distribution.Compiler import Distribution.ReadE import Distribution.Text- ( Text(..), display ) import qualified Distribution.Compat.ReadP as Parse import qualified Text.PrettyPrint as Disp-import Distribution.ModuleName-import Distribution.Package ( Dependency(..)- , PackageName- , InstalledPackageId )-import Distribution.PackageDescription- ( FlagName(..), FlagAssignment )+import Distribution.Package+import Distribution.PackageDescription hiding (Flag) import Distribution.Simple.Command hiding (boolOpt, boolOpt') import qualified Distribution.Simple.Command as Command-import Distribution.Simple.Compiler- ( CompilerFlavor(..), defaultCompilerFlavor, PackageDB(..)- , DebugInfoLevel(..), flagToDebugInfoLevel- , OptimisationLevel(..), flagToOptimisationLevel- , absolutePackageDBPath )+import Distribution.Simple.Compiler hiding (Flag) import Distribution.Simple.Utils- ( wrapText, wrapLine, lowercase, intercalate )-import Distribution.Simple.Program (Program(..), ProgramConfiguration,- requireProgram,- programInvocation, progInvokePath, progInvokeArgs,- knownPrograms,- addKnownProgram, emptyProgramConfiguration,- haddockProgram, ghcProgram, gccProgram, ldProgram)+import Distribution.Simple.Program import Distribution.Simple.InstallDirs- ( InstallDirs(..), CopyDest(..),- PathTemplate, toPathTemplate, fromPathTemplate ) import Distribution.Verbosity import Distribution.Utils.NubList--import Control.Monad (liftM) import Distribution.Compat.Binary (Binary)-import Data.List ( sort )-import Data.Char ( isSpace, isAlpha )-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid ( Monoid(..) )-#endif-import GHC.Generics (Generic)+import Distribution.Compat.Semigroup as Semi +import Control.Applicative as A ( Applicative(..), (<*) )+import Control.Monad ( liftM )+import Data.List ( sort )+import Data.Maybe ( listToMaybe )+import Data.Char ( isSpace, isAlpha )+import GHC.Generics ( Generic )+ -- FIXME Not sure where this should live defaultDistPref :: FilePath defaultDistPref = "dist"@@ -144,9 +129,12 @@ instance Monoid (Flag a) where mempty = NoFlag- _ `mappend` f@(Flag _) = f- f `mappend` NoFlag = f+ mappend = (Semi.<>) +instance Semigroup (Flag a) where+ _ <> f@(Flag _) = f+ f <> NoFlag = f+ instance Bounded a => Bounded (Flag a) where minBound = toFlag minBound maxBound = toFlag maxBound@@ -201,7 +189,7 @@ data GlobalFlags = GlobalFlags { globalVersion :: Flag Bool, globalNumericVersion :: Flag Bool- }+ } deriving (Generic) defaultGlobalFlags :: GlobalFlags defaultGlobalFlags = GlobalFlags {@@ -226,8 +214,8 @@ align str = str ++ replicate (maxlen - length str) ' ' in "Commands:\n"- ++ unlines [ " " ++ align name ++ " " ++ description- | (name, description) <- cmdDescs ]+ ++ unlines [ " " ++ align name ++ " " ++ descr+ | (name, descr) <- cmdDescs ] ++ "\n" ++ "For more information about a command use\n" ++ " " ++ pname ++ " COMMAND --help\n\n"@@ -252,20 +240,78 @@ emptyGlobalFlags = mempty instance Monoid GlobalFlags where- mempty = GlobalFlags {- globalVersion = mempty,- globalNumericVersion = mempty- }- mappend a b = GlobalFlags {- globalVersion = combine globalVersion,- globalNumericVersion = combine globalNumericVersion- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup GlobalFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * Config flags -- ------------------------------------------------------------ +-- | Policy for relaxing upper bounds in dependencies. For example, given+-- 'build-depends: array >= 0.3 && < 0.5', are we allowed to relax the upper+-- bound and choose a version of 'array' that is greater or equal to 0.5? By+-- default the upper bounds are always strictly honored.+data AllowNewer =++ -- | Default: honor the upper bounds in all dependencies, never choose+ -- versions newer than allowed.+ AllowNewerNone++ -- | Ignore upper bounds in dependencies on the given packages.+ | AllowNewerSome [AllowNewerDep]++ -- | Ignore upper bounds in dependencies on all packages.+ | AllowNewerAll+ deriving (Eq, Read, Show, Generic)++-- | Dependencies can be relaxed either for all packages in the install plan, or+-- only for some packages.+data AllowNewerDep = AllowNewerDep PackageName+ | AllowNewerDepScoped PackageName PackageName+ deriving (Eq, Read, Show, Generic)++instance Text AllowNewerDep where+ disp (AllowNewerDep p0) = disp p0+ disp (AllowNewerDepScoped p0 p1) = disp p0 Disp.<> Disp.colon Disp.<> disp p1++ parse = scopedP Parse.<++ normalP+ where+ scopedP = AllowNewerDepScoped `fmap` parse A.<* Parse.char ':' A.<*> parse+ normalP = AllowNewerDep `fmap` parse++instance Binary AllowNewer+instance Binary AllowNewerDep++instance Semigroup AllowNewer where+ AllowNewerNone <> r = r+ l@AllowNewerAll <> _ = l+ l@(AllowNewerSome _) <> AllowNewerNone = l+ (AllowNewerSome _) <> r@AllowNewerAll = r+ (AllowNewerSome a) <> (AllowNewerSome b) = AllowNewerSome (a ++ b)++instance Monoid AllowNewer where+ mempty = AllowNewerNone+ mappend = (Semi.<>)++-- | Convert 'AllowNewer' to a boolean.+isAllowNewer :: AllowNewer -> Bool+isAllowNewer AllowNewerNone = False+isAllowNewer (AllowNewerSome _) = True+isAllowNewer AllowNewerAll = True++allowNewerParser :: Parse.ReadP r (Maybe AllowNewer)+allowNewerParser =+ (Just . AllowNewerSome) `fmap` Parse.sepBy1 parse (Parse.char ',')++allowNewerPrinter :: (Maybe AllowNewer) -> [Maybe String]+allowNewerPrinter Nothing = []+allowNewerPrinter (Just AllowNewerNone) = []+allowNewerPrinter (Just AllowNewerAll) = [Nothing]+allowNewerPrinter (Just (AllowNewerSome pkgs)) = map (Just . display) $ pkgs+ -- | Flags to @configure@ command. -- -- IMPORTANT: every time a new flag is added, 'D.C.Setup.filterConfigureFlags'@@ -275,8 +321,8 @@ -- because the type of configure is constrained by the UserHooks. -- when we change UserHooks next we should pass the initial -- ProgramConfiguration directly and not via ConfigFlags- configPrograms :: ProgramConfiguration, -- ^All programs that cabal may- -- run+ configPrograms_ :: Last' ProgramConfiguration, -- ^All programs that+ -- @cabal@ may run configProgramPaths :: [(String, FilePath)], -- ^user specified programs paths configProgramArgs :: [(String, [String])], -- ^user specified programs args@@ -293,6 +339,12 @@ -- executables. configProfExe :: Flag Bool, -- ^Enable profiling in the -- executables.+ configProf :: Flag Bool, -- ^Enable profiling in the library+ -- and executables.+ configProfDetail :: Flag ProfDetailLevel, -- ^Profiling detail level+ -- in the library and executables.+ configProfLibDetail :: Flag ProfDetailLevel, -- ^Profiling detail level+ -- in the library configConfigureArgs :: [String], -- ^Extra arguments to @configure@ configOptimization :: Flag OptimisationLevel, -- ^Enable optimization. configProgPrefix :: Flag PathTemplate, -- ^Installed executable prefix.@@ -301,7 +353,10 @@ -- paths configScratchDir :: Flag FilePath, configExtraLibDirs :: [FilePath], -- ^ path to search for extra libraries+ configExtraFrameworkDirs :: [FilePath], -- ^ path to search for extra+ -- frameworks (OS X only) configExtraIncludeDirs :: [FilePath], -- ^ path to search for header files+ configIPID :: Flag String, -- ^ explicit IPID to be used configDistPref :: Flag FilePath, -- ^"dist" prefix configVerbosity :: Flag Verbosity, -- ^verbosity level@@ -313,8 +368,7 @@ configStripLibs :: Flag Bool, -- ^Enable library stripping configConstraints :: [Dependency], -- ^Additional constraints for -- dependencies.- configDependencies :: [(PackageName, InstalledPackageId)],- configInstantiateWith :: [(ModuleName, (InstalledPackageId, ModuleName))],+ configDependencies :: [(PackageName, UnitId)], -- ^The packages depended on. configConfigurationsFlags :: FlagAssignment, configTests :: Flag Bool, -- ^Enable test suite compilation@@ -327,12 +381,20 @@ configFlagError :: Flag String, -- ^Halt and show an error message indicating an error in flag assignment configRelocatable :: Flag Bool, -- ^ Enable relocatable package built- configDebugInfo :: Flag DebugInfoLevel -- ^ Emit debug info.+ configDebugInfo :: Flag DebugInfoLevel, -- ^ Emit debug info.+ configAllowNewer :: Maybe AllowNewer+ -- ^ Ignore upper bounds on all or some dependencies. Wrapped in 'Maybe' to+ -- distinguish between "default" and "explicitly disabled". } deriving (Generic, Read, Show) instance Binary ConfigFlags +-- | More convenient version of 'configPrograms'. Results in an+-- 'error' if internal invariant is violated.+configPrograms :: ConfigFlags -> ProgramConfiguration+configPrograms = maybe (error "FIXME: remove configPrograms") id . getLast' . configPrograms_+ configAbsolutePaths :: ConfigFlags -> IO ConfigFlags configAbsolutePaths f = (\v -> f { configPackageDBs = v })@@ -341,17 +403,20 @@ defaultConfigFlags :: ProgramConfiguration -> ConfigFlags defaultConfigFlags progConf = emptyConfigFlags {- configPrograms = progConf,+ configPrograms_ = pure progConf, configHcFlavor = maybe NoFlag Flag defaultCompilerFlavor, configVanillaLib = Flag True, configProfLib = NoFlag, configSharedLib = NoFlag, configDynExe = Flag False, configProfExe = NoFlag,+ configProf = NoFlag,+ configProfDetail = NoFlag,+ configProfLibDetail= NoFlag, configOptimization = Flag NormalOptimisation, configProgPrefix = Flag (toPathTemplate ""), configProgSuffix = Flag (toPathTemplate ""),- configDistPref = Flag defaultDistPref,+ configDistPref = NoFlag, configVerbosity = Flag normal, configUserInstall = Flag False, --TODO: reverse this #if defined(mingw32_HOST_OS)@@ -370,7 +435,8 @@ configExactConfiguration = Flag False, configFlagError = NoFlag, configRelocatable = Flag False,- configDebugInfo = Flag NoDebugInfo+ configDebugInfo = Flag NoDebugInfo,+ configAllowNewer = Nothing } configureCommand :: ProgramConfiguration -> CommandUI ConfigFlags@@ -383,7 +449,7 @@ ++ "\n" ++ "The configuration affects several other commands, " ++ "including build, test, bench, run, repl.\n"- , commandNotes = Just (\_ -> programFlagsDescription progConf)+ , commandNotes = Just $ \_pname -> programFlagsDescription progConf , commandUsage = \pname -> "Usage: " ++ pname ++ " configure [FLAGS]\n" , commandDefaultFlags = defaultConfigFlags progConf@@ -460,19 +526,8 @@ (boolOpt [] []) ,option "" ["profiling"]- "Executable profiling (requires library profiling)"- -- HACK: See #2409. Thankfully, this is 1.22-specific.- (\flags ->- case (configProfLib flags, configProfExe flags) of- (Flag a, Flag b)- | (a == b)- && ("cabalConfProf", "/TRUE") `elem` configProgramPaths flags- -> configProfExe flags- _ -> NoFlag)- (\v flags -> flags- { configProfLib = v, configProfExe = v- , configProgramPaths = ("cabalConfProf", "/TRUE")- : configProgramPaths flags })+ "Executable and library profiling"+ configProf (\v flags -> flags { configProf = v }) (boolOpt [] []) ,option "" ["executable-profiling"]@@ -480,6 +535,19 @@ configProfExe (\v flags -> flags { configProfExe = v }) (boolOpt [] []) + ,option "" ["profiling-detail"]+ ("Profiling detail level for executable and library (default, " +++ "none, exported-functions, toplevel-functions, all-functions).")+ configProfDetail (\v flags -> flags { configProfDetail = v })+ (reqArg' "level" (Flag . flagToProfDetailLevel)+ showProfDetailLevelFlag)++ ,option "" ["library-profiling-detail"]+ "Profiling detail level for libraries only."+ configProfLibDetail (\v flags -> flags { configProfLibDetail = v })+ (reqArg' "level" (Flag . flagToProfDetailLevel)+ showProfDetailLevelFlag)+ ,multiOption "optimization" configOptimization (\v flags -> flags { configOptimization = v }) [optArg' "n" (Flag . flagToOptimisationLevel)@@ -542,7 +610,12 @@ (boolOpt' ([],["user"]) ([], ["global"])) ,option "" ["package-db"]- "Use a given package database (to satisfy dependencies and register in). May be a specific file, 'global', 'user' or 'clear'."+ ( "Append the given package database to the list of package"+ ++ " databases used (to satisfy dependencies and register into)."+ ++ " May be a specific file, 'global' or 'user'. The initial list"+ ++ " is ['global'], ['global', 'user'], or ['global', $sandbox],"+ ++ " depending on context. Use 'clear' to reset the list to empty."+ ++ " See the user guide for details.") configPackageDBs (\v flags -> flags { configPackageDBs = v }) (reqArg' "DB" readPackageDbList showPackageDbList) @@ -556,11 +629,22 @@ configExtraIncludeDirs (\v flags -> flags {configExtraIncludeDirs = v}) (reqArg' "PATH" (\x -> [x]) id) + ,option "" ["ipid"]+ "Installed package ID to compile this package as"+ configIPID (\v flags -> flags {configIPID = v})+ (reqArgFlag "IPID")+ ,option "" ["extra-lib-dirs"] "A list of directories to search for external libraries" configExtraLibDirs (\v flags -> flags {configExtraLibDirs = v}) (reqArg' "PATH" (\x -> [x]) id) + ,option "" ["extra-framework-dirs"]+ "A list of directories to search for external frameworks (OS X only)"+ configExtraFrameworkDirs+ (\v flags -> flags {configExtraFrameworkDirs = v})+ (reqArg' "PATH" (\x -> [x]) id)+ ,option "" ["extra-prog-path"] "A list of directories to search for required programs (in addition to the normal search locations)" configProgramPathExtra (\v flags -> flags {configProgramPathExtra = v})@@ -580,13 +664,6 @@ (readP_to_E (const "dependency expected") ((\x -> [x]) `fmap` parseDependency)) (map (\x -> display (fst x) ++ "=" ++ display (snd x)))) - ,option "" ["instantiate-with"]- "A mapping of signature names to concrete module instantiations. E.g., --instantiate-with=\"Map=Data.Map.Strict@containers-0.5.5.1-inplace\""- configInstantiateWith (\v flags -> flags { configInstantiateWith = v })- (reqArg "NAME=PKG:MOD"- (readP_to_E (const "signature mapping expected") ((\x -> [x]) `fmap` parseHoleMapEntry))- (map (\(n,(p,m)) -> display n ++ "=" ++ display m ++ "@" ++ display p)))- ,option "" ["tests"] "dependency checking and compilation for test suites listed in the package description file." configTests (\v flags -> flags { configTests = v })@@ -602,6 +679,13 @@ configLibCoverage (\v flags -> flags { configLibCoverage = v }) (boolOpt [] []) + ,option [] ["allow-newer"]+ ("Ignore upper bounds in all dependencies or DEPS")+ configAllowNewer (\v flags -> flags { configAllowNewer = v})+ (optArg "DEPS"+ (readP_to_E ("Cannot parse the list of packages: " ++) allowNewerParser)+ (Just AllowNewerAll) allowNewerPrinter)+ ,option "" ["exact-configuration"] "All direct dependencies and flags are provided on the command line." configExactConfiguration@@ -649,23 +733,17 @@ showPackageDb (Just UserPackageDB) = "user" showPackageDb (Just (SpecificPackageDB db)) = db +showProfDetailLevelFlag :: Flag ProfDetailLevel -> [String]+showProfDetailLevelFlag NoFlag = []+showProfDetailLevelFlag (Flag dl) = [showProfDetailLevel dl] -parseDependency :: Parse.ReadP r (PackageName, InstalledPackageId)+parseDependency :: Parse.ReadP r (PackageName, UnitId) parseDependency = do x <- parse _ <- Parse.char '=' y <- parse return (x, y) -parseHoleMapEntry :: Parse.ReadP r (ModuleName, (InstalledPackageId, ModuleName))-parseHoleMapEntry = do- x <- parse- _ <- Parse.char '='- y <- parse- _ <- Parse.char '@'- z <- parse- return (x, (z, y))- installDirsOptions :: [OptionField (InstallDirs (Flag PathTemplate))] installDirsOptions = [ option "" ["prefix"]@@ -732,92 +810,12 @@ emptyConfigFlags = mempty instance Monoid ConfigFlags where- mempty = ConfigFlags {- configPrograms = error "FIXME: remove configPrograms",- configProgramPaths = mempty,- configProgramArgs = mempty,- configProgramPathExtra = mempty,- configHcFlavor = mempty,- configHcPath = mempty,- configHcPkg = mempty,- configVanillaLib = mempty,- configProfLib = mempty,- configSharedLib = mempty,- configDynExe = mempty,- configProfExe = mempty,- configConfigureArgs = mempty,- configOptimization = mempty,- configProgPrefix = mempty,- configProgSuffix = mempty,- configInstallDirs = mempty,- configScratchDir = mempty,- configDistPref = mempty,- configVerbosity = mempty,- configUserInstall = mempty,- configPackageDBs = mempty,- configGHCiLib = mempty,- configSplitObjs = mempty,- configStripExes = mempty,- configStripLibs = mempty,- configExtraLibDirs = mempty,- configConstraints = mempty,- configDependencies = mempty,- configInstantiateWith = mempty,- configExtraIncludeDirs = mempty,- configConfigurationsFlags = mempty,- configTests = mempty,- configCoverage = mempty,- configLibCoverage = mempty,- configExactConfiguration = mempty,- configBenchmarks = mempty,- configFlagError = mempty,- configRelocatable = mempty,- configDebugInfo = mempty- }- mappend a b = ConfigFlags {- configPrograms = configPrograms b,- configProgramPaths = combine configProgramPaths,- configProgramArgs = combine configProgramArgs,- configProgramPathExtra = combine configProgramPathExtra,- configHcFlavor = combine configHcFlavor,- configHcPath = combine configHcPath,- configHcPkg = combine configHcPkg,- configVanillaLib = combine configVanillaLib,- configProfLib = combine configProfLib,- configSharedLib = combine configSharedLib,- configDynExe = combine configDynExe,- configProfExe = combine configProfExe,- configConfigureArgs = combine configConfigureArgs,- configOptimization = combine configOptimization,- configProgPrefix = combine configProgPrefix,- configProgSuffix = combine configProgSuffix,- configInstallDirs = combine configInstallDirs,- configScratchDir = combine configScratchDir,- configDistPref = combine configDistPref,- configVerbosity = combine configVerbosity,- configUserInstall = combine configUserInstall,- configPackageDBs = combine configPackageDBs,- configGHCiLib = combine configGHCiLib,- configSplitObjs = combine configSplitObjs,- configStripExes = combine configStripExes,- configStripLibs = combine configStripLibs,- configExtraLibDirs = combine configExtraLibDirs,- configConstraints = combine configConstraints,- configDependencies = combine configDependencies,- configInstantiateWith = combine configInstantiateWith,- configExtraIncludeDirs = combine configExtraIncludeDirs,- configConfigurationsFlags = combine configConfigurationsFlags,- configTests = combine configTests,- configCoverage = combine configCoverage,- configLibCoverage = combine configLibCoverage,- configExactConfiguration = combine configExactConfiguration,- configBenchmarks = combine configBenchmarks,- configFlagError = combine configFlagError,- configRelocatable = combine configRelocatable,- configDebugInfo = combine configDebugInfo- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup ConfigFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * Copy flags -- ------------------------------------------------------------@@ -828,12 +826,12 @@ copyDistPref :: Flag FilePath, copyVerbosity :: Flag Verbosity }- deriving Show+ deriving (Show, Generic) defaultCopyFlags :: CopyFlags defaultCopyFlags = CopyFlags { copyDest = Flag NoCopyDest,- copyDistPref = Flag defaultDistPref,+ copyDistPref = NoFlag, copyVerbosity = Flag normal } @@ -867,18 +865,12 @@ emptyCopyFlags = mempty instance Monoid CopyFlags where- mempty = CopyFlags {- copyDest = mempty,- copyDistPref = mempty,- copyVerbosity = mempty- }- mappend a b = CopyFlags {- copyDest = combine copyDest,- copyDistPref = combine copyDistPref,- copyVerbosity = combine copyVerbosity- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup CopyFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * Install flags -- ------------------------------------------------------------@@ -891,12 +883,12 @@ installInPlace :: Flag Bool, installVerbosity :: Flag Verbosity }- deriving Show+ deriving (Show, Generic) defaultInstallFlags :: InstallFlags defaultInstallFlags = InstallFlags { installPackageDB = NoFlag,- installDistPref = Flag defaultDistPref,+ installDistPref = NoFlag, installUseWrapper = Flag False, installInPlace = Flag False, installVerbosity = Flag normal@@ -944,22 +936,12 @@ emptyInstallFlags = mempty instance Monoid InstallFlags where- mempty = InstallFlags{- installPackageDB = mempty,- installDistPref = mempty,- installUseWrapper = mempty,- installInPlace = mempty,- installVerbosity = mempty- }- mappend a b = InstallFlags{- installPackageDB = combine installPackageDB,- installDistPref = combine installDistPref,- installUseWrapper = combine installUseWrapper,- installInPlace = combine installInPlace,- installVerbosity = combine installVerbosity- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup InstallFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * SDist flags -- ------------------------------------------------------------@@ -972,13 +954,13 @@ sDistListSources :: Flag FilePath, sDistVerbosity :: Flag Verbosity }- deriving Show+ deriving (Show, Generic) defaultSDistFlags :: SDistFlags defaultSDistFlags = SDistFlags { sDistSnapshot = Flag False, sDistDirectory = mempty,- sDistDistPref = Flag defaultDistPref,+ sDistDistPref = NoFlag, sDistListSources = mempty, sDistVerbosity = Flag normal }@@ -1021,22 +1003,12 @@ emptySDistFlags = mempty instance Monoid SDistFlags where- mempty = SDistFlags {- sDistSnapshot = mempty,- sDistDirectory = mempty,- sDistDistPref = mempty,- sDistListSources = mempty,- sDistVerbosity = mempty- }- mappend a b = SDistFlags {- sDistSnapshot = combine sDistSnapshot,- sDistDirectory = combine sDistDirectory,- sDistDistPref = combine sDistDistPref,- sDistListSources = combine sDistListSources,- sDistVerbosity = combine sDistVerbosity- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup SDistFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * Register flags -- ------------------------------------------------------------@@ -1052,7 +1024,7 @@ regPrintId :: Flag Bool, regVerbosity :: Flag Verbosity }- deriving Show+ deriving (Show, Generic) defaultRegisterFlags :: RegisterFlags defaultRegisterFlags = RegisterFlags {@@ -1060,7 +1032,7 @@ regGenScript = Flag False, regGenPkgConf = NoFlag, regInPlace = Flag False,- regDistPref = Flag defaultDistPref,+ regDistPref = NoFlag, regPrintId = Flag False, regVerbosity = Flag normal }@@ -1144,26 +1116,12 @@ emptyRegisterFlags = mempty instance Monoid RegisterFlags where- mempty = RegisterFlags {- regPackageDB = mempty,- regGenScript = mempty,- regGenPkgConf = mempty,- regInPlace = mempty,- regPrintId = mempty,- regDistPref = mempty,- regVerbosity = mempty- }- mappend a b = RegisterFlags {- regPackageDB = combine regPackageDB,- regGenScript = combine regGenScript,- regGenPkgConf = combine regGenPkgConf,- regInPlace = combine regInPlace,- regPrintId = combine regPrintId,- regDistPref = combine regDistPref,- regVerbosity = combine regVerbosity- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup RegisterFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * HsColour flags -- ------------------------------------------------------------@@ -1176,7 +1134,7 @@ hscolourDistPref :: Flag FilePath, hscolourVerbosity :: Flag Verbosity }- deriving Show+ deriving (Show, Generic) emptyHscolourFlags :: HscolourFlags emptyHscolourFlags = mempty@@ -1187,29 +1145,17 @@ hscolourExecutables = Flag False, hscolourTestSuites = Flag False, hscolourBenchmarks = Flag False,- hscolourDistPref = Flag defaultDistPref,+ hscolourDistPref = NoFlag, hscolourVerbosity = Flag normal } instance Monoid HscolourFlags where- mempty = HscolourFlags {- hscolourCSS = mempty,- hscolourExecutables = mempty,- hscolourTestSuites = mempty,- hscolourBenchmarks = mempty,- hscolourDistPref = mempty,- hscolourVerbosity = mempty- }- mappend a b = HscolourFlags {- hscolourCSS = combine hscolourCSS,- hscolourExecutables = combine hscolourExecutables,- hscolourTestSuites = combine hscolourTestSuites,- hscolourBenchmarks = combine hscolourBenchmarks,- hscolourDistPref = combine hscolourDistPref,- hscolourVerbosity = combine hscolourVerbosity- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup HscolourFlags where+ (<>) = gmappend+ hscolourCommand :: CommandUI HscolourFlags hscolourCommand = CommandUI { commandName = "hscolour"@@ -1269,6 +1215,7 @@ haddockHoogle :: Flag Bool, haddockHtml :: Flag Bool, haddockHtmlLocation :: Flag String,+ haddockForHackage :: Flag Bool, haddockExecutables :: Flag Bool, haddockTestSuites :: Flag Bool, haddockBenchmarks :: Flag Bool,@@ -1281,7 +1228,7 @@ haddockKeepTempFiles:: Flag Bool, haddockVerbosity :: Flag Verbosity }- deriving Show+ deriving (Show, Generic) defaultHaddockFlags :: HaddockFlags defaultHaddockFlags = HaddockFlags {@@ -1290,6 +1237,7 @@ haddockHoogle = Flag False, haddockHtml = Flag False, haddockHtmlLocation = NoFlag,+ haddockForHackage = Flag False, haddockExecutables = Flag False, haddockTestSuites = Flag False, haddockBenchmarks = Flag False,@@ -1298,7 +1246,7 @@ haddockHscolour = Flag False, haddockHscolourCss = NoFlag, haddockContents = NoFlag,- haddockDistPref = Flag defaultDistPref,+ haddockDistPref = NoFlag, haddockKeepTempFiles= Flag False, haddockVerbosity = Flag normal }@@ -1355,6 +1303,11 @@ haddockHtmlLocation (\v flags -> flags { haddockHtmlLocation = v }) (reqArgFlag "URL") + ,option "" ["for-hackage"]+ "Collection of flags to generate documentation suitable for upload to hackage"+ haddockForHackage (\v flags -> flags { haddockForHackage = v })+ trueArg+ ,option "" ["executables"] "Run haddock for Executables targets" haddockExecutables (\v flags -> flags { haddockExecutables = v })@@ -1412,44 +1365,12 @@ emptyHaddockFlags = mempty instance Monoid HaddockFlags where- mempty = HaddockFlags {- haddockProgramPaths = mempty,- haddockProgramArgs = mempty,- haddockHoogle = mempty,- haddockHtml = mempty,- haddockHtmlLocation = mempty,- haddockExecutables = mempty,- haddockTestSuites = mempty,- haddockBenchmarks = mempty,- haddockInternal = mempty,- haddockCss = mempty,- haddockHscolour = mempty,- haddockHscolourCss = mempty,- haddockContents = mempty,- haddockDistPref = mempty,- haddockKeepTempFiles= mempty,- haddockVerbosity = mempty- }- mappend a b = HaddockFlags {- haddockProgramPaths = combine haddockProgramPaths,- haddockProgramArgs = combine haddockProgramArgs,- haddockHoogle = combine haddockHoogle,- haddockHtml = combine haddockHoogle,- haddockHtmlLocation = combine haddockHtmlLocation,- haddockExecutables = combine haddockExecutables,- haddockTestSuites = combine haddockTestSuites,- haddockBenchmarks = combine haddockBenchmarks,- haddockInternal = combine haddockInternal,- haddockCss = combine haddockCss,- haddockHscolour = combine haddockHscolour,- haddockHscolourCss = combine haddockHscolourCss,- haddockContents = combine haddockContents,- haddockDistPref = combine haddockDistPref,- haddockKeepTempFiles= combine haddockKeepTempFiles,- haddockVerbosity = combine haddockVerbosity- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup HaddockFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * Clean flags -- ------------------------------------------------------------@@ -1459,12 +1380,12 @@ cleanDistPref :: Flag FilePath, cleanVerbosity :: Flag Verbosity }- deriving Show+ deriving (Show, Generic) defaultCleanFlags :: CleanFlags defaultCleanFlags = CleanFlags { cleanSaveConf = Flag False,- cleanDistPref = Flag defaultDistPref,+ cleanDistPref = NoFlag, cleanVerbosity = Flag normal } @@ -1495,18 +1416,12 @@ emptyCleanFlags = mempty instance Monoid CleanFlags where- mempty = CleanFlags {- cleanSaveConf = mempty,- cleanDistPref = mempty,- cleanVerbosity = mempty- }- mappend a b = CleanFlags {- cleanSaveConf = combine cleanSaveConf,- cleanDistPref = combine cleanDistPref,- cleanVerbosity = combine cleanVerbosity- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup CleanFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * Build flags -- ------------------------------------------------------------@@ -1521,7 +1436,7 @@ -- UserHooks stop us from passing extra info in other ways buildArgs :: [String] }- deriving Show+ deriving (Show, Generic) {-# DEPRECATED buildVerbose "Use buildVerbosity instead" #-} buildVerbose :: BuildFlags -> Verbosity@@ -1531,7 +1446,7 @@ defaultBuildFlags = BuildFlags { buildProgramPaths = mempty, buildProgramArgs = [],- buildDistPref = Flag defaultDistPref,+ buildDistPref = mempty, buildVerbosity = Flag normal, buildNumJobs = mempty, buildArgs = []@@ -1596,24 +1511,12 @@ emptyBuildFlags = mempty instance Monoid BuildFlags where- mempty = BuildFlags {- buildProgramPaths = mempty,- buildProgramArgs = mempty,- buildVerbosity = mempty,- buildDistPref = mempty,- buildNumJobs = mempty,- buildArgs = mempty- }- mappend a b = BuildFlags {- buildProgramPaths = combine buildProgramPaths,- buildProgramArgs = combine buildProgramArgs,- buildVerbosity = combine buildVerbosity,- buildDistPref = combine buildDistPref,- buildNumJobs = combine buildNumJobs,- buildArgs = combine buildArgs- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup BuildFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * REPL Flags -- ------------------------------------------------------------@@ -1625,34 +1528,24 @@ replVerbosity :: Flag Verbosity, replReload :: Flag Bool }- deriving Show+ deriving (Show, Generic) defaultReplFlags :: ReplFlags defaultReplFlags = ReplFlags { replProgramPaths = mempty, replProgramArgs = [],- replDistPref = Flag defaultDistPref,+ replDistPref = NoFlag, replVerbosity = Flag normal, replReload = Flag False } instance Monoid ReplFlags where- mempty = ReplFlags {- replProgramPaths = mempty,- replProgramArgs = mempty,- replVerbosity = mempty,- replDistPref = mempty,- replReload = mempty- }- mappend a b = ReplFlags {- replProgramPaths = combine replProgramPaths,- replProgramArgs = combine replProgramArgs,- replVerbosity = combine replVerbosity,- replDistPref = combine replDistPref,- replReload = combine replReload- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup ReplFlags where+ (<>) = gmappend+ replCommand :: ProgramConfiguration -> CommandUI ReplFlags replCommand progConf = CommandUI { commandName = "repl"@@ -1725,7 +1618,7 @@ -- * Test flags -- ------------------------------------------------------------ -data TestShowDetails = Never | Failures | Always | Streaming+data TestShowDetails = Never | Failures | Always | Streaming | Direct deriving (Eq, Ord, Enum, Bounded, Show) knownTestShowDetails :: [TestShowDetails]@@ -1745,8 +1638,11 @@ --TODO: do we need this instance? instance Monoid TestShowDetails where mempty = Never- mappend a b = if a < b then b else a+ mappend = (Semi.<>) +instance Semigroup TestShowDetails where+ a <> b = if a < b then b else a+ data TestFlags = TestFlags { testDistPref :: Flag FilePath, testVerbosity :: Flag Verbosity,@@ -1756,11 +1652,11 @@ testKeepTix :: Flag Bool, -- TODO: think about if/how options are passed to test exes testOptions :: [PathTemplate]- }+ } deriving (Generic) defaultTestFlags :: TestFlags defaultTestFlags = TestFlags {- testDistPref = Flag defaultDistPref,+ testDistPref = NoFlag, testVerbosity = Flag normal, testHumanLog = toFlag $ toPathTemplate $ "$pkgid-$test-suite.log", testMachineLog = toFlag $ toPathTemplate $ "$pkgid.log",@@ -1813,7 +1709,8 @@ ("'always': always show results of individual test cases. " ++ "'never': never show results of individual test cases. " ++ "'failures': show results of failing test cases. "- ++ "'streaming': show results of test cases in real time.")+ ++ "'streaming': show results of test cases in real time."+ ++ "'direct': send results of test cases in real time; no log file.") testShowDetails (\v flags -> flags { testShowDetails = v }) (reqArg "FILTER" (readP_to_E (\_ -> "--show-details flag expects one of "@@ -1847,26 +1744,12 @@ emptyTestFlags = mempty instance Monoid TestFlags where- mempty = TestFlags {- testDistPref = mempty,- testVerbosity = mempty,- testHumanLog = mempty,- testMachineLog = mempty,- testShowDetails = mempty,- testKeepTix = mempty,- testOptions = mempty- }- mappend a b = TestFlags {- testDistPref = combine testDistPref,- testVerbosity = combine testVerbosity,- testHumanLog = combine testHumanLog,- testMachineLog = combine testMachineLog,- testShowDetails = combine testShowDetails,- testKeepTix = combine testKeepTix,- testOptions = combine testOptions- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup TestFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * Benchmark flags -- ------------------------------------------------------------@@ -1875,11 +1758,11 @@ benchmarkDistPref :: Flag FilePath, benchmarkVerbosity :: Flag Verbosity, benchmarkOptions :: [PathTemplate]- }+ } deriving (Generic) defaultBenchmarkFlags :: BenchmarkFlags defaultBenchmarkFlags = BenchmarkFlags {- benchmarkDistPref = Flag defaultDistPref,+ benchmarkDistPref = NoFlag, benchmarkVerbosity = Flag normal, benchmarkOptions = [] }@@ -1934,18 +1817,12 @@ emptyBenchmarkFlags = mempty instance Monoid BenchmarkFlags where- mempty = BenchmarkFlags {- benchmarkDistPref = mempty,- benchmarkVerbosity = mempty,- benchmarkOptions = mempty- }- mappend a b = BenchmarkFlags {- benchmarkDistPref = combine benchmarkDistPref,- benchmarkVerbosity = combine benchmarkVerbosity,- benchmarkOptions = combine benchmarkOptions- }- where combine field = field a `mappend` field b+ mempty = gmempty+ mappend = (Semi.<>) +instance Semigroup BenchmarkFlags where+ (<>) = gmappend+ -- ------------------------------------------------------------ -- * Shared options utils -- ------------------------------------------------------------@@ -2105,6 +1982,10 @@ -- ------------------------------------------------------------ -- * Other Utils -- ------------------------------------------------------------++readPToMaybe :: Parse.ReadP a a -> String -> Maybe a+readPToMaybe p str = listToMaybe [ r | (r,s) <- Parse.readP_to_S p str+ , all isSpace s ] -- | Arguments to pass to a @configure@ script, e.g. generated by -- @autoconf@.
Distribution/Simple/SrcDist.hs view
@@ -40,35 +40,20 @@ ) where -import Distribution.PackageDescription- ( PackageDescription(..), BuildInfo(..), Executable(..), Library(..)- , TestSuite(..), TestSuiteInterface(..), Benchmark(..)- , BenchmarkInterface(..) )-import Distribution.PackageDescription.Check- ( PackageCheck(..), checkConfiguredPackage, checkPackageFiles )+import Distribution.PackageDescription hiding (Flag)+import Distribution.PackageDescription.Check hiding (doesFileExist) import Distribution.Package- ( PackageIdentifier(pkgVersion), Package(..), packageVersion )-import Distribution.ModuleName (ModuleName)+import Distribution.ModuleName import qualified Distribution.ModuleName as ModuleName import Distribution.Version- ( Version(versionBranch) ) import Distribution.Simple.Utils- ( createDirectoryIfMissingVerbose, withUTF8FileContents, writeUTF8File- , installOrdinaryFiles, installMaybeExecutableFiles- , findFile, findFileWithExtension, matchFileGlob- , withTempDirectory, defaultPackageDesc- , die, warn, notice, info, setupMessage )-import Distribution.Simple.Setup ( Flag(..), SDistFlags(..)- , fromFlag, flagToMaybe)-import Distribution.Simple.PreProcess ( PPSuffixHandler, ppSuffixes- , preprocessComponent )+import Distribution.Simple.Setup+import Distribution.Simple.PreProcess import Distribution.Simple.LocalBuildInfo- ( LocalBuildInfo(..), withAllComponentsInBuildOrder )-import Distribution.Simple.BuildPaths ( autogenModuleName )-import Distribution.Simple.Program ( defaultProgramConfiguration, requireProgram,- runProgram, programProperties, tarProgram )+import Distribution.Simple.BuildPaths+import Distribution.Simple.Program import Distribution.Text- ( display )+import Distribution.Verbosity import Control.Monad(when, unless, forM) import Data.Char (toLower)@@ -78,7 +63,6 @@ import Data.Time (UTCTime, getCurrentTime, toGregorian, utctDay) import System.Directory ( doesFileExist ) import System.IO (IOMode(WriteMode), hPutStrLn, withFile)-import Distribution.Verbosity (Verbosity) import System.FilePath ( (</>), (<.>), dropExtension, isAbsolute ) @@ -169,19 +153,19 @@ fmap concat . sequence $ [ -- Library sources.- withLib $ \Library { exposedModules = modules, libBuildInfo = libBi } ->+ withAllLib $ \Library { exposedModules = modules, libBuildInfo = libBi } -> allSourcesBuildInfo libBi pps modules -- Executables sources. , fmap concat- . withExe $ \Executable { modulePath = mainPath, buildInfo = exeBi } -> do+ . withAllExe $ \Executable { modulePath = mainPath, buildInfo = exeBi } -> do biSrcs <- allSourcesBuildInfo exeBi pps [] mainSrc <- findMainExeFile exeBi pps mainPath return (mainSrc:biSrcs) -- Test suites sources. , fmap concat- . withTest $ \t -> do+ . withAllTest $ \t -> do let bi = testBuildInfo t case testInterface t of TestSuiteExeV10 _ mainPath -> do@@ -200,7 +184,7 @@ -- Benchmarks sources. , fmap concat- . withBenchmark $ \bm -> do+ . withAllBenchmark $ \bm -> do let bi = benchmarkBuildInfo bm case benchmarkInterface bm of BenchmarkExeV10 _ mainPath -> do@@ -229,7 +213,7 @@ , return (licenseFiles pkg_descr) -- Install-include files.- , withLib $ \ l -> do+ , withAllLib $ \ l -> do let lbi = libBuildInfo l relincdirs = "." : filter (not.isAbsolute) (includeDirs lbi) mapM (fmap snd . findIncludeFile relincdirs) (installIncludes lbi)@@ -244,10 +228,10 @@ where -- We have to deal with all libs and executables, so we have local -- versions of these functions that ignore the 'buildable' attribute:- withLib action = maybe (return []) action (library pkg_descr)- withExe action = mapM action (executables pkg_descr)- withTest action = mapM action (testSuites pkg_descr)- withBenchmark action = mapM action (benchmarks pkg_descr)+ withAllLib action = maybe (return []) action (library pkg_descr)+ withAllExe action = mapM action (executables pkg_descr)+ withAllTest action = mapM action (testSuites pkg_descr)+ withAllBenchmark action = mapM action (benchmarks pkg_descr) -- |Prepare a directory tree of source files.@@ -432,10 +416,10 @@ -> IO [FilePath] allSourcesBuildInfo bi pps modules = do let searchDirs = hsSourceDirs bi- sources <- sequence+ sources <- fmap concat $ sequence $ [ let file = ModuleName.toFilePath module_- in findFileWithExtension suffixes searchDirs file- >>= maybe (notFound module_) return+ in findAllFilesWithExtension suffixes searchDirs file+ >>= nonEmpty (notFound module_) return | module_ <- modules ++ otherModules bi ] bootFiles <- sequence [ let file = ModuleName.toFilePath module_@@ -446,6 +430,8 @@ return $ sources ++ catMaybes bootFiles ++ cSources bi ++ jsSources bi where+ nonEmpty x _ [] = x+ nonEmpty _ f xs = f xs suffixes = ppSuffixes pps ++ ["hs", "lhs"] notFound m = die $ "Error: Could not find module: " ++ display m ++ " with any suffix: " ++ show suffixes@@ -455,8 +441,9 @@ printPackageProblems verbosity pkg_descr = do ioChecks <- checkPackageFiles pkg_descr "." let pureChecks = checkConfiguredPackage pkg_descr- isDistError (PackageDistSuspicious _) = False- isDistError _ = True+ isDistError (PackageDistSuspicious _) = False+ isDistError (PackageDistSuspiciousWarn _) = False+ isDistError _ = True (errors, warnings) = partition isDistError (pureChecks ++ ioChecks) unless (null errors) $ notice verbosity $ "Distribution quality errors:\n"
Distribution/Simple/Test.hs view
@@ -16,23 +16,17 @@ ) where import qualified Distribution.PackageDescription as PD- ( PackageDescription(..), BuildInfo(buildable)- , TestSuite(..)- , TestSuiteInterface(..), testType, hasTests )-import Distribution.Simple.Compiler ( compilerInfo )-import Distribution.Simple.Hpc ( markupPackage )+import Distribution.Simple.Compiler+import Distribution.Simple.Hpc import Distribution.Simple.InstallDirs- ( fromPathTemplate, initialPathTemplateEnv, substPathTemplate- , PathTemplate ) import qualified Distribution.Simple.LocalBuildInfo as LBI- ( LocalBuildInfo(..) )-import Distribution.Simple.Setup ( TestFlags(..), fromFlag, configCoverage )-import Distribution.Simple.UserHooks ( Args )+import Distribution.Simple.Setup+import Distribution.Simple.UserHooks import qualified Distribution.Simple.Test.ExeV10 as ExeV10 import qualified Distribution.Simple.Test.LibV09 as LibV09 import Distribution.Simple.Test.Log-import Distribution.Simple.Utils ( die, notice )-import Distribution.TestSuite ( Result(..) )+import Distribution.Simple.Utils+import Distribution.TestSuite import Distribution.Text import Control.Monad ( when, unless, filterM )@@ -132,5 +126,5 @@ fromPathTemplate $ substPathTemplate env template where env = initialPathTemplateEnv- (PD.package pkg_descr) (LBI.pkgKey lbi)+ (PD.package pkg_descr) (LBI.localUnitId lbi) (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi)
Distribution/Simple/Test/ExeV10.hs view
@@ -2,26 +2,22 @@ ( runTest ) where -import Distribution.Compat.CreatePipe ( createPipe )-import Distribution.Compat.Environment ( getEnvironment )+import Distribution.Compat.CreatePipe+import Distribution.Compat.Environment import qualified Distribution.PackageDescription as PD-import Distribution.Simple.Build.PathsModule ( pkgPathEnvVar )-import Distribution.Simple.BuildPaths ( exeExtension )-import Distribution.Simple.Compiler ( compilerInfo )-import Distribution.Simple.Hpc ( guessWay, markupTest, tixDir, tixFilePath )+import Distribution.Simple.Build.PathsModule+import Distribution.Simple.BuildPaths+import Distribution.Simple.Compiler+import Distribution.Simple.Hpc import Distribution.Simple.InstallDirs- ( fromPathTemplate, initialPathTemplateEnv, PathTemplateVariable(..)- , substPathTemplate , toPathTemplate, PathTemplate ) import qualified Distribution.Simple.LocalBuildInfo as LBI import Distribution.Simple.Setup- ( TestFlags(..), TestShowDetails(..), fromFlag, configCoverage ) import Distribution.Simple.Test.Log import Distribution.Simple.Utils- ( die, notice, rawSystemIOWithEnv, addLibraryPath )-import Distribution.System ( Platform (..) )+import Distribution.System import Distribution.TestSuite import Distribution.Text-import Distribution.Verbosity ( normal )+import Distribution.Verbosity import Control.Concurrent (forkIO) import Control.Monad ( unless, void, when )@@ -30,7 +26,7 @@ , getCurrentDirectory, removeDirectoryRecursive ) import System.Exit ( ExitCode(..) ) import System.FilePath ( (</>), (<.>) )-import System.IO ( hGetContents, hPutStr, stdout )+import System.IO ( hGetContents, hPutStr, stdout, stderr ) runTest :: PD.PackageDescription -> LBI.LocalBuildInfo@@ -63,16 +59,21 @@ -- Write summary notices indicating start of test suite notice verbosity $ summarizeSuiteStart $ PD.testName suite - (rOut, wOut) <- createPipe+ (wOut, wErr, logText) <- case details of+ Direct -> return (stdout, stderr, "")+ _ -> do+ (rOut, wOut) <- createPipe - -- Read test executable's output lazily (returns immediately)- logText <- hGetContents rOut- -- Force the IO manager to drain the test output pipe- void $ forkIO $ length logText `seq` return ()+ -- Read test executable's output lazily (returns immediately)+ logText <- hGetContents rOut+ -- Force the IO manager to drain the test output pipe+ void $ forkIO $ length logText `seq` return () - -- '--show-details=streaming': print the log output in another thread- when (details == Streaming) $ void $ forkIO $ hPutStr stdout logText+ -- '--show-details=streaming': print the log output in another thread+ when (details == Streaming) $ void $ forkIO $ hPutStr stdout logText + return (wOut, wOut, logText)+ -- Run the test executable let opts = map (testOption pkg_descr lbi suite) (testOptions flags)@@ -93,7 +94,7 @@ exit <- rawSystemIOWithEnv verbosity cmd opts Nothing (Just shellEnv') -- these handles are automatically closed- Nothing (Just wOut) (Just wOut)+ Nothing (Just wOut) (Just wErr) -- Generate TestSuiteLog from executable exit code and a machine- -- readable test log.@@ -112,12 +113,10 @@ -- Show the contents of the human-readable log file on the terminal -- if there is a failure and/or detailed output is requested let whenPrinting = when $- (details > Never)- && (not (suitePassed $ testLogs suiteLog) || details == Always)+ ( details == Always ||+ details == Failures && not (suitePassed $ testLogs suiteLog)) -- verbosity overrides show-details && verbosity >= normal- -- if streaming, we already printed the log- && details /= Streaming whenPrinting $ putStr $ unlines $ lines logText -- Write summary notice to terminal indicating end of test suite@@ -163,6 +162,6 @@ fromPathTemplate $ substPathTemplate env template where env = initialPathTemplateEnv- (PD.package pkg_descr) (LBI.pkgKey lbi)+ (PD.package pkg_descr) (LBI.localUnitId lbi) (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) ++ [(TestSuiteNameVar, toPathTemplate $ PD.testName suite)]
Distribution/Simple/Test/LibV09.hs view
@@ -6,28 +6,24 @@ , writeSimpleTestStub ) where -import Distribution.Compat.CreatePipe ( createPipe )-import Distribution.Compat.Environment ( getEnvironment )-import Distribution.Compat.TempFile ( openTempFile )-import Distribution.ModuleName ( ModuleName )+import Distribution.Compat.CreatePipe+import Distribution.Compat.Environment+import Distribution.Compat.Internal.TempFile+import Distribution.ModuleName import qualified Distribution.PackageDescription as PD-import Distribution.Simple.Build.PathsModule ( pkgPathEnvVar )-import Distribution.Simple.BuildPaths ( exeExtension )-import Distribution.Simple.Compiler ( compilerInfo )-import Distribution.Simple.Hpc ( guessWay, markupTest, tixDir, tixFilePath )+import Distribution.Simple.Build.PathsModule+import Distribution.Simple.BuildPaths+import Distribution.Simple.Compiler+import Distribution.Simple.Hpc import Distribution.Simple.InstallDirs- ( fromPathTemplate, initialPathTemplateEnv, PathTemplateVariable(..)- , substPathTemplate , toPathTemplate, PathTemplate ) import qualified Distribution.Simple.LocalBuildInfo as LBI import Distribution.Simple.Setup- ( TestFlags(..), TestShowDetails(..), fromFlag, configCoverage ) import Distribution.Simple.Test.Log import Distribution.Simple.Utils- ( die, notice, rawSystemIOWithEnv, addLibraryPath )-import Distribution.System ( Platform (..) )+import Distribution.System import Distribution.TestSuite import Distribution.Text-import Distribution.Verbosity ( normal )+import Distribution.Verbosity import Control.Exception ( bracket ) import Control.Monad ( when, unless )@@ -39,6 +35,7 @@ import System.Exit ( ExitCode(..), exitWith ) import System.FilePath ( (</>), (<.>) ) import System.IO ( hClose, hGetContents, hPutStr )+import System.Process (StdStream(..), waitForProcess) runTest :: PD.PackageDescription -> LBI.LocalBuildInfo@@ -73,16 +70,11 @@ suiteLog <- bracket openCabalTemp deleteIfExists $ \tempLog -> do - (rIn, wIn) <- createPipe (rOut, wOut) <- createPipe - -- Prepare standard input for test executable- --appendFile tempInput $ show (tempInput, PD.testName suite)- hPutStr wIn $ show (tempLog, PD.testName suite)- hClose wIn- -- Run test executable- _ <- do let opts = map (testOption pkg_descr lbi suite) $ testOptions flags+ (Just wIn, _, _, process) <- do+ let opts = map (testOption pkg_descr lbi suite) $ testOptions flags dataDirPath = pwd </> PD.dataDir pkg_descr tixFile = pwd </> tixFilePath distPref way (PD.testName suite) pkgPathEnv = (pkgPathEnvVar pkg_descr "datadir", dataDirPath)@@ -101,10 +93,23 @@ True False lbi clbi return (addLibraryPath os paths shellEnv) else return shellEnv- rawSystemIOWithEnv verbosity cmd opts Nothing (Just shellEnv')- -- these handles are closed automatically- (Just rIn) (Just wOut) (Just wOut)+ createProcessWithEnv verbosity cmd opts Nothing (Just shellEnv')+ -- these handles are closed automatically+ CreatePipe (UseHandle wOut) (UseHandle wOut) + hPutStr wIn $ show (tempLog, PD.testName suite)+ hClose wIn++ -- Append contents of temporary log file to the final human-+ -- readable log file+ logText <- hGetContents rOut+ -- Force the IO manager to drain the test output pipe+ length logText `seq` return ()++ exitcode <- waitForProcess process+ unless (exitcode == ExitSuccess) $ do+ debug verbosity $ cmd ++ " returned " ++ show exitcode+ -- Generate final log file name let finalLogName l = testLogDir </> testSuiteLogPath@@ -118,9 +123,6 @@ -- Write summary notice to log file indicating start of test suite appendFile (logFile suiteLog) $ summarizeSuiteStart $ PD.testName suite - -- Append contents of temporary log file to the final human-- -- readable log file- logText <- hGetContents rOut appendFile (logFile suiteLog) logText -- Write end-of-suite summary notice to log file@@ -167,7 +169,7 @@ fromPathTemplate $ substPathTemplate env template where env = initialPathTemplateEnv- (PD.package pkg_descr) (LBI.pkgKey lbi)+ (PD.package pkg_descr) (LBI.localUnitId lbi) (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) ++ [(TestSuiteNameVar, toPathTemplate $ PD.testName suite)]
Distribution/Simple/Test/Log.hs view
@@ -11,18 +11,16 @@ , testSuiteLogPath ) where -import Distribution.Package ( PackageId )+import Distribution.Package import qualified Distribution.PackageDescription as PD-import Distribution.Simple.Compiler ( Compiler(..), compilerInfo, CompilerId )+import Distribution.Simple.Compiler import Distribution.Simple.InstallDirs- ( fromPathTemplate, initialPathTemplateEnv, PathTemplateVariable(..)- , substPathTemplate , toPathTemplate, PathTemplate ) import qualified Distribution.Simple.LocalBuildInfo as LBI-import Distribution.Simple.Setup ( TestShowDetails(..) )-import Distribution.Simple.Utils ( notice )-import Distribution.System ( Platform )-import Distribution.TestSuite ( Options, Result(..) )-import Distribution.Verbosity ( Verbosity )+import Distribution.Simple.Setup+import Distribution.Simple.Utils+import Distribution.System+import Distribution.TestSuite+import Distribution.Verbosity import Control.Monad ( when ) import Data.Char ( toUpper )@@ -109,13 +107,13 @@ -> String -- ^ test suite name -> TestLogs -- ^ test suite results -> FilePath-testSuiteLogPath template pkg_descr lbi name result =+testSuiteLogPath template pkg_descr lbi test_name result = fromPathTemplate $ substPathTemplate env template where env = initialPathTemplateEnv- (PD.package pkg_descr) (LBI.pkgKey lbi)+ (PD.package pkg_descr) (LBI.localUnitId lbi) (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi)- ++ [ (TestSuiteNameVar, toPathTemplate name)+ ++ [ (TestSuiteNameVar, toPathTemplate test_name) , (TestSuiteResultVar, toPathTemplate $ resultString result) ]
Distribution/Simple/UHC.hs view
@@ -16,15 +16,12 @@ module Distribution.Simple.UHC ( configure, getInstalledPackages,- buildLib, buildExe, installLib, registerPackage+ buildLib, buildExe, installLib, registerPackage, inplacePackageDbPath ) where -import Control.Monad-import Data.List-import qualified Data.Map as M ( empty ) import Distribution.Compat.ReadP import Distribution.InstalledPackageInfo-import Distribution.Package hiding (installedPackageId)+import Distribution.Package hiding (installedUnitId) import Distribution.PackageDescription import Distribution.Simple.BuildPaths import Distribution.Simple.Compiler as C@@ -35,10 +32,14 @@ import Distribution.Text import Distribution.Verbosity import Distribution.Version+import Distribution.System import Language.Haskell.Extension++import Control.Monad+import Data.List+import qualified Data.Map as M ( empty ) import System.Directory import System.FilePath-import Distribution.System ( Platform ) -- ----------------------------------------------------------------------------- -- Configuring@@ -91,14 +92,13 @@ -> IO InstalledPackageIndex getInstalledPackages verbosity comp packagedbs conf = do let compilerid = compilerId comp- systemPkgDir <- rawSystemProgramStdoutConf verbosity uhcProgram conf ["--meta-pkgdir-system"]+ systemPkgDir <- getGlobalPackageDir verbosity conf userPkgDir <- getUserPackageDir let pkgDirs = nub (concatMap (packageDbPaths userPkgDir systemPkgDir) packagedbs) -- putStrLn $ "pkgdirs: " ++ show pkgDirs- -- call to "lines" necessary, because pkgdir contains an extra newline at the end- pkgs <- liftM (map addBuiltinVersions . concat) .- mapM (\ d -> getDirectoryContents d >>= filterM (isPkgDir (display compilerid) d)) .- concatMap lines $ pkgDirs+ pkgs <- liftM (map addBuiltinVersions . concat) $+ mapM (\ d -> getDirectoryContents d >>= filterM (isPkgDir (display compilerid) d))+ pkgDirs -- putStrLn $ "pkgs: " ++ show pkgs let iPkgs = map mkInstalledPackageInfo $@@ -107,9 +107,16 @@ -- putStrLn $ "installed pkgs: " ++ show iPkgs return (fromList iPkgs) +getGlobalPackageDir :: Verbosity -> ProgramConfiguration -> IO FilePath+getGlobalPackageDir verbosity conf = do+ output <- rawSystemProgramStdoutConf verbosity+ uhcProgram conf ["--meta-pkgdir-system"]+ -- call to "lines" necessary, because pkgdir contains an extra newline at the end+ let [pkgdir] = lines output+ return pkgdir+ getUserPackageDir :: IO FilePath-getUserPackageDir =- do+getUserPackageDir = do homeDir <- getHomeDirectory return $ homeDir </> ".cabal" </> "lib" -- TODO: determine in some other way @@ -150,8 +157,8 @@ -- | Create a trivial package info from a directory name. mkInstalledPackageInfo :: PackageId -> InstalledPackageInfo mkInstalledPackageInfo p = emptyInstalledPackageInfo- { installedPackageId = InstalledPackageId (display p),- sourcePackageId = p }+ { installedUnitId = mkLegacyUnitId p,+ sourcePackageId = p } -- -----------------------------------------------------------------------------@@ -161,7 +168,7 @@ -> Library -> ComponentLocalBuildInfo -> IO () buildLib verbosity pkg_descr lbi lib clbi = do - systemPkgDir <- rawSystemProgramStdoutConf verbosity uhcProgram (withPrograms lbi) ["--meta-pkgdir-system"]+ systemPkgDir <- getGlobalPackageDir verbosity (withPrograms lbi) userPkgDir <- getUserPackageDir let runUhcProg = rawSystemProgramConf verbosity uhcProgram (withPrograms lbi) let uhcArgs = -- set package name@@ -183,7 +190,7 @@ buildExe :: Verbosity -> PackageDescription -> LocalBuildInfo -> Executable -> ComponentLocalBuildInfo -> IO () buildExe verbosity _pkg_descr lbi exe clbi = do- systemPkgDir <- rawSystemProgramStdoutConf verbosity uhcProgram (withPrograms lbi) ["--meta-pkgdir-system"]+ systemPkgDir <- getGlobalPackageDir verbosity (withPrograms lbi) userPkgDir <- getUserPackageDir let runUhcProg = rawSystemProgramConf verbosity uhcProgram (withPrograms lbi) let uhcArgs = -- common flags lib/exe@@ -236,8 +243,8 @@ installLib :: Verbosity -> LocalBuildInfo -> FilePath -> FilePath -> FilePath- -> PackageDescription -> Library -> IO ()-installLib verbosity _lbi targetDir _dynlibTargetDir builtDir pkg _library = do+ -> PackageDescription -> Library -> ComponentLocalBuildInfo -> IO ()+installLib verbosity _lbi targetDir _dynlibTargetDir builtDir pkg _library _clbi = do -- putStrLn $ "dest: " ++ targetDir -- putStrLn $ "built: " ++ builtDir installDirectoryContents verbosity (builtDir </> display (packageId pkg)) targetDir@@ -258,19 +265,23 @@ registerPackage :: Verbosity- -> InstalledPackageInfo- -> PackageDescription- -> LocalBuildInfo- -> Bool+ -> Compiler+ -> ProgramConfiguration -> PackageDBStack+ -> InstalledPackageInfo -> IO ()-registerPackage verbosity installedPkgInfo pkg lbi inplace _packageDbs = do- let installDirs = absoluteInstallDirs pkg lbi NoCopyDest- pkgdir | inplace = buildDir lbi </> uhcPackageDir (display pkgid) (display compilerid)- | otherwise = libdir installDirs </> uhcPackageSubDir (display compilerid)+registerPackage verbosity comp progdb packageDbs installedPkgInfo = do+ dbdir <- case last packageDbs of+ GlobalPackageDB -> getGlobalPackageDir verbosity progdb+ UserPackageDB -> getUserPackageDir+ SpecificPackageDB dir -> return dir+ let pkgdir = dbdir </> uhcPackageDir (display pkgid) (display compilerid) createDirectoryIfMissingVerbose verbosity True pkgdir writeUTF8File (pkgdir </> installedPkgConfig) (showInstalledPackageInfo installedPkgInfo) where- pkgid = packageId pkg- compilerid = compilerId (compiler lbi)+ pkgid = sourcePackageId installedPkgInfo+ compilerid = compilerId comp++inplacePackageDbPath :: LocalBuildInfo -> FilePath+inplacePackageDbPath lbi = buildDir lbi
Distribution/Simple/UserHooks.hs view
@@ -29,16 +29,11 @@ ) where import Distribution.PackageDescription- (PackageDescription, GenericPackageDescription,- HookedBuildInfo, emptyHookedBuildInfo)-import Distribution.Simple.Program (Program)-import Distribution.Simple.Command (noExtraFlags)-import Distribution.Simple.PreProcess (PPSuffixHandler)+import Distribution.Simple.Program+import Distribution.Simple.Command+import Distribution.Simple.PreProcess import Distribution.Simple.Setup- (ConfigFlags, BuildFlags, ReplFlags, CleanFlags, CopyFlags,- InstallFlags, SDistFlags, RegisterFlags, HscolourFlags,- HaddockFlags, TestFlags, BenchmarkFlags)-import Distribution.Simple.LocalBuildInfo (LocalBuildInfo)+import Distribution.Simple.LocalBuildInfo type Args = [String]
Distribution/Simple/Utils.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, ForeignFunctionInterface #-}+{-# LANGUAGE CPP, ForeignFunctionInterface, ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Simple.Utils@@ -26,6 +26,9 @@ debugNoWrap, chattyTry, printRawCommandAndArgs, printRawCommandAndArgsAndEnv, + -- * exceptions+ handleDoesNotExist,+ -- * running programs rawSystemExit, rawSystemExitCode,@@ -33,6 +36,7 @@ rawSystemStdout, rawSystemStdInOut, rawSystemIOWithEnv,+ createProcessWithEnv, maybeExit, xargs, findProgramLocation,@@ -64,12 +68,15 @@ -- * file names currentDir, shortRelativePath,+ dropExeExtension,+ exeExtensions, -- * finding files findFile, findFirstFile, findFileWithExtension, findFileWithExtension',+ findAllFilesWithExtension, findModuleFile, findModuleFiles, getDirectoryContentsRecursive,@@ -113,6 +120,11 @@ writeUTF8File, normaliseLineEndings, + -- * BOM+ startsWithBOM,+ fileHasBOM,+ ignoreBOM,+ -- * generic utils dropWhileEndLE, takeWhileEndLE,@@ -125,20 +137,51 @@ listUnionRight, ordNub, ordNubRight,+ safeTail, wrapText, wrapLine, ) where +import Distribution.Text+import Distribution.Package+import Distribution.ModuleName as ModuleName+import Distribution.System+import Distribution.Version+import Distribution.Compat.CopyFile+import Distribution.Compat.Internal.TempFile+import Distribution.Compat.Exception+import Distribution.Verbosity++#if __GLASGOW_HASKELL__ < 711+#ifdef VERSION_base+#define BOOTSTRAPPED_CABAL 1+#endif+#else+#ifdef CURRENT_PACKAGE_KEY+#define BOOTSTRAPPED_CABAL 1+#endif+#endif++#ifdef BOOTSTRAPPED_CABAL+import qualified Paths_Cabal (version)+#endif+ import Control.Monad- ( join, when, unless, filterM )+ ( when, unless, filterM ) import Control.Concurrent.MVar ( newEmptyMVar, putMVar, takeMVar )-import Data.List- ( nub, unfoldr, isPrefixOf, tails, intercalate )-import Data.Char as Char- ( isDigit, toLower, chr, ord ) import Data.Bits ( Bits((.|.), (.&.), shiftL, shiftR) )+import Data.Char as Char+ ( isDigit, toLower, chr, ord )+import Data.Foldable+ ( traverse_ )+import Data.List+ ( nub, unfoldr, intercalate, isInfixOf )+import Data.Typeable+ ( cast )+import Data.Ord+ ( comparing ) import qualified Data.ByteString.Lazy as BS import qualified Data.ByteString.Lazy.Char8 as BS.Char8 import qualified Data.Set as Set@@ -163,7 +206,7 @@ , IOMode(ReadMode), hSetBinaryMode , hGetContents, stderr, stdout, hPutStr, hFlush, hClose ) import System.IO.Error as IO.Error- ( isDoesNotExistError, isAlreadyExistsError+ ( isDoesNotExistError, isAlreadyExistsError, isUserError , ioeSetFileName, ioeGetFileName, ioeGetErrorString ) import System.IO.Error ( ioeSetLocation, ioeGetLocation )@@ -171,40 +214,17 @@ ( unsafeInterleaveIO ) import qualified Control.Exception as Exception -import Distribution.Text- ( display, simpleParse )-import Distribution.Package- ( PackageIdentifier )-import Distribution.ModuleName (ModuleName)-import qualified Distribution.ModuleName as ModuleName-import Distribution.System- ( OS (..) )-import Distribution.Version- (Version(..))- import Control.Exception (IOException, evaluate, throwIO) import Control.Concurrent (forkIO) import qualified System.Process as Process ( CreateProcess(..), StdStream(..), proc) import System.Process- ( createProcess, rawSystem, runInteractiveProcess+ ( ProcessHandle, createProcess, rawSystem, runInteractiveProcess , showCommandForUser, waitForProcess)-import Distribution.Compat.CopyFile- ( copyFile, copyOrdinaryFile, copyExecutableFile- , setFileOrdinary, setFileExecutable, setDirOrdinary )-import Distribution.Compat.TempFile- ( openTempFile, createTempDirectory )-import Distribution.Compat.Exception- ( tryIO, catchIO, catchExit )-import Distribution.Verbosity -#ifdef VERSION_base-import qualified Paths_Cabal (version)-#endif- -- We only get our own version number when we're building with ourselves cabalVersion :: Version-#if defined(VERSION_base)+#if defined(BOOTSTRAPPED_CABAL) cabalVersion = Paths_Cabal.version #elif defined(CABAL_VERSION) cabalVersion = Version [CABAL_VERSION] []@@ -227,24 +247,49 @@ die :: String -> IO a die msg = ioError (userError msg) -topHandlerWith :: (Exception.IOException -> IO a) -> IO a -> IO a-topHandlerWith cont prog = catchIO prog handle+topHandlerWith :: forall a. (Exception.SomeException -> IO a) -> IO a -> IO a+topHandlerWith cont prog =+ Exception.catches prog [+ Exception.Handler rethrowAsyncExceptions+ , Exception.Handler rethrowExitStatus+ , Exception.Handler handle+ ] where- handle ioe = do+ -- Let async exceptions rise to the top for the default top-handler+ rethrowAsyncExceptions :: Exception.AsyncException -> IO a+ rethrowAsyncExceptions = throwIO++ -- ExitCode gets thrown asynchronously too, and we don't want to print it+ rethrowExitStatus :: ExitCode -> IO a+ rethrowExitStatus = throwIO++ -- Print all other exceptions+ handle :: Exception.SomeException -> IO a+ handle se = do hFlush stdout pname <- getProgName- hPutStr stderr (mesage pname)- cont ioe- where- mesage pname = wrapText (pname ++ ": " ++ file ++ detail)- file = case ioeGetFileName ioe of- Nothing -> ""- Just path -> path ++ location ++ ": "- location = case ioeGetLocation ioe of- l@(n:_) | Char.isDigit n -> ':' : l- _ -> ""- detail = ioeGetErrorString ioe+ hPutStr stderr (wrapText (message pname se))+ cont se + message :: String -> Exception.SomeException -> String+ message pname (Exception.SomeException se) =+ case cast se :: Maybe Exception.IOException of+ Just ioe | isUserError ioe ->+ let file = case ioeGetFileName ioe of+ Nothing -> ""+ Just path -> path ++ location ++ ": "+ location = case ioeGetLocation ioe of+ l@(n:_) | Char.isDigit n -> ':' : l+ _ -> ""+ detail = ioeGetErrorString ioe+ in pname ++ ": " ++ file ++ detail+ _ ->+#if __GLASGOW_HASKELL__ < 710+ show se+#else+ Exception.displayException se+#endif+ topHandler :: IO a -> IO a topHandler prog = topHandlerWith (const $ exitWith (ExitFailure 1)) prog @@ -310,6 +355,14 @@ catchIO action $ \exception -> putStrLn $ "Error while " ++ desc ++ ": " ++ show exception +-- | Run an IO computation, returning @e@ if it raises a "file+-- does not exist" error.+handleDoesNotExist :: a -> IO a -> IO a+handleDoesNotExist e =+ Exception.handleJust+ (\ioe -> if isDoesNotExistError ioe then Just ioe else Nothing)+ (\_ -> return e)+ -- ----------------------------------------------------------------------------- -- Helper functions @@ -356,7 +409,7 @@ -> IO () printRawCommandAndArgsAndEnv verbosity path args menv | verbosity >= deafening = do- maybe (return ()) (putStrLn . ("Environment: " ++) . show) menv+ traverse_ (putStrLn . ("Environment: " ++) . show) menv print (path, args) | verbosity >= verbose = putStrLn $ showCommandForUser path args | otherwise = return ()@@ -415,29 +468,47 @@ -> Maybe Handle -- ^ stderr -> IO ExitCode rawSystemIOWithEnv verbosity path args mcwd menv inp out err = do+ (_,_,_,ph) <- createProcessWithEnv verbosity path args mcwd menv+ (mbToStd inp) (mbToStd out) (mbToStd err)+ exitcode <- waitForProcess ph+ unless (exitcode == ExitSuccess) $ do+ debug verbosity $ path ++ " returned " ++ show exitcode+ return exitcode+ where+ mbToStd :: Maybe Handle -> Process.StdStream+ mbToStd = maybe Process.Inherit Process.UseHandle++createProcessWithEnv ::+ Verbosity+ -> FilePath+ -> [String]+ -> Maybe FilePath -- ^ New working dir or inherit+ -> Maybe [(String, String)] -- ^ New environment or inherit+ -> Process.StdStream -- ^ stdin+ -> Process.StdStream -- ^ stdout+ -> Process.StdStream -- ^ stderr+ -> IO (Maybe Handle, Maybe Handle, Maybe Handle,ProcessHandle)+ -- ^ Any handles created for stdin, stdout, or stderr+ -- with 'CreateProcess', and a handle to the process.+createProcessWithEnv verbosity path args mcwd menv inp out err = do printRawCommandAndArgsAndEnv verbosity path args menv hFlush stdout- (_,_,_,ph) <- createProcess $- (Process.proc path args) { Process.cwd = mcwd- , Process.env = menv- , Process.std_in = mbToStd inp- , Process.std_out = mbToStd out- , Process.std_err = mbToStd err+ (inp', out', err', ph) <- createProcess $+ (Process.proc path args) {+ Process.cwd = mcwd+ , Process.env = menv+ , Process.std_in = inp+ , Process.std_out = out+ , Process.std_err = err #ifdef MIN_VERSION_process #if MIN_VERSION_process(1,2,0) -- delegate_ctlc has been added in process 1.2, and we still want to be able to -- bootstrap GHC on systems not having that version- , Process.delegate_ctlc = True+ , Process.delegate_ctlc = True #endif #endif- }- exitcode <- waitForProcess ph- unless (exitcode == ExitSuccess) $ do- debug verbosity $ path ++ " returned " ++ show exitcode- return exitcode- where- mbToStd :: Maybe Handle -> Process.StdStream- mbToStd = maybe Process.Inherit Process.UseHandle+ }+ return (inp', out', err', ph) -- | Run a command and return its output. --@@ -519,6 +590,8 @@ return (out, err, exitcode) +{-# DEPRECATED findProgramLocation+ "No longer used within Cabal, try findProgramOnSearchPath" #-} -- | Look for a program on the path. findProgramLocation :: Verbosity -> FilePath -> IO (Maybe FilePath) findProgramLocation verbosity prog = do@@ -610,6 +683,16 @@ | path <- nub searchPath , ext <- nub extensions ] +findAllFilesWithExtension :: [String]+ -> [FilePath]+ -> FilePath+ -> IO [FilePath]+findAllFilesWithExtension extensions searchPath basename =+ findAllFiles id+ [ path </> basename <.> ext+ | path <- nub searchPath+ , ext <- nub extensions ]+ -- | Like 'findFileWithExtension' but returns which element of the search path -- the file was found in, and the file path relative to that base directory. --@@ -631,6 +714,9 @@ then return (Just x) else findFirst xs +findAllFiles :: (a -> FilePath) -> [a] -> IO [a]+findAllFiles file = filterM (doesFileExist . file)+ -- | Finds the files corresponding to a list of Haskell module names. -- -- As 'findModuleFile' but for a list of module names.@@ -950,7 +1036,8 @@ copyDirectoryRecursive verbosity srcDir destDir = do info verbosity ("copy directory '" ++ srcDir ++ "' to '" ++ destDir ++ "'.") srcFiles <- getDirectoryContentsRecursive srcDir- copyFilesWith (const copyFile) verbosity destDir [ (srcDir, f) | f <- srcFiles ]+ copyFilesWith (const copyFile) verbosity destDir [ (srcDir, f)+ | f <- srcFiles ] ------------------- -- File permissions@@ -1012,7 +1099,8 @@ Exception.bracket (openTempFile tmpDir template) (\(name, handle) -> do hClose handle- unless (optKeepTempFiles opts) $ removeFile name)+ unless (optKeepTempFiles opts) $+ handleDoesNotExist () . removeFile $ name) (uncurry action) -- | Create and use a temporary directory.@@ -1038,7 +1126,8 @@ withTempDirectoryEx _verbosity opts targetDir template = Exception.bracket (createTempDirectory targetDir template)- (unless (optKeepTempFiles opts) . removeDirectoryRecursive)+ (unless (optKeepTempFiles opts)+ . handleDoesNotExist () . removeDirectoryRecursive) ----------------------------------- -- Safely reading and writing files@@ -1105,6 +1194,24 @@ | x == y = dropCommonPrefix xs ys dropCommonPrefix xs ys = (xs,ys) +-- | Drop the extension if it's one of 'exeExtensions', or return the path+-- unchanged.+dropExeExtension :: FilePath -> FilePath+dropExeExtension filepath =+ case splitExtension filepath of+ (filepath', extension) | extension `elem` exeExtensions -> filepath'+ | otherwise -> filepath++-- | List of possible executable file extensions on the current platform.+exeExtensions :: [String]+exeExtensions = case buildOS of+ -- Possible improvement: on Windows, read the list of extensions from the+ -- PATHEXT environment variable. By default PATHEXT is ".com; .exe; .bat;+ -- .cmd".+ Windows -> ["", "exe"]+ Ghcjs -> ["", "exe"]+ _ -> [""]+ -- ------------------------------------------------------------ -- * Finding the description file -- ------------------------------------------------------------@@ -1143,7 +1250,7 @@ -- |Like 'findPackageDesc', but calls 'die' in case of error. tryFindPackageDesc :: FilePath -> IO FilePath-tryFindPackageDesc dir = join . fmap (either die return) $ findPackageDesc dir+tryFindPackageDesc dir = either die return =<< findPackageDesc dir -- |Optional auxiliary package information file (/pkgname/@.buildinfo@) defaultHookedPackageDesc :: IO (Maybe FilePath)@@ -1236,6 +1343,16 @@ : toUTF8 cs where w = ord c +-- | Whether BOM is at the beginning of the input+startsWithBOM :: String -> Bool+startsWithBOM ('\xFEFF':_) = True+startsWithBOM _ = False++-- | Check whether a file has Unicode byte order mark (BOM).+fileHasBOM :: FilePath -> IO Bool+fileHasBOM f = fmap (startsWithBOM . fromUTF8)+ . hGetContents =<< openBinaryFile f ReadMode+ -- | Ignore a Unicode byte order mark (BOM) at the beginning of the input -- ignoreBOM :: String -> String@@ -1357,14 +1474,13 @@ where bSet = Set.fromList b +-- | A total variant of 'tail'.+safeTail :: [a] -> [a]+safeTail [] = []+safeTail (_:xs) = xs+ equating :: Eq a => (b -> a) -> b -> b -> Bool equating p x y = p x == p y--comparing :: Ord a => (b -> a) -> b -> b -> Ordering-comparing p x y = p x `compare` p y--isInfixOf :: String -> String -> Bool-isInfixOf needle haystack = any (isPrefixOf needle) (tails haystack) lowercase :: String -> String lowercase = map Char.toLower
Distribution/System.hs view
@@ -13,7 +13,7 @@ -- probably know about the 'System.Info.os' however using that is very -- inconvenient because it is a string and different Haskell implementations -- do not agree on using the same strings for the same platforms! (In--- particular see the controversy over \"windows\" vs \"ming32\"). So to make it+-- particular see the controversy over \"windows\" vs \"mingw32\"). So to make it -- more consistent and easy to use we have an 'OS' enumeration. -- module Distribution.System (@@ -28,18 +28,24 @@ -- * Platform is a pair of arch and OS Platform(..), buildPlatform,- platformFromTriple+ platformFromTriple,++ -- * Internal+ knownOSs,+ knownArches ) where import qualified System.Info (os, arch)-import qualified Data.Char as Char (toLower, isAlphaNum)+import qualified Data.Char as Char (toLower, isAlphaNum, isAlpha) -import Distribution.Compat.Binary (Binary)+import Distribution.Compat.Binary+import Distribution.Text+import qualified Distribution.Compat.ReadP as Parse++import Control.Monad (liftM2) import Data.Data (Data) import Data.Typeable (Typeable) import Data.Maybe (fromMaybe, listToMaybe)-import Distribution.Text (Text(..), display)-import qualified Distribution.Compat.ReadP as Parse import GHC.Generics (Generic) import qualified Text.PrettyPrint as Disp import Text.PrettyPrint ((<>))@@ -72,30 +78,28 @@ | DragonFly | Solaris | AIX | HPUX | IRIX -- ageing Unix OSs | HaLVM -- bare metal / VMs / hypervisors- | IOS -- iOS+ | Hurd -- GNU's microkernel+ | IOS | Android -- mobile OSs | Ghcjs | OtherOS String deriving (Eq, Generic, Ord, Show, Read, Typeable, Data) instance Binary OS ---TODO: decide how to handle Android and iOS.--- They are like Linux and OSX but with some differences.--- Should they be separate from Linux/OS X, or a subtype?--- e.g. should we have os(linux) && os(android) true simultaneously?- knownOSs :: [OS] knownOSs = [Linux, Windows, OSX ,FreeBSD, OpenBSD, NetBSD, DragonFly ,Solaris, AIX, HPUX, IRIX ,HaLVM- ,IOS+ ,Hurd+ ,IOS, Android ,Ghcjs] osAliases :: ClassificationStrictness -> OS -> [String] osAliases Permissive Windows = ["mingw32", "win32", "cygwin32"] osAliases Compat Windows = ["mingw32", "win32"] osAliases _ OSX = ["darwin"]+osAliases _ Hurd = ["gnu"] osAliases Permissive FreeBSD = ["kfreebsdgnu"] osAliases Compat FreeBSD = ["kfreebsdgnu"] osAliases Permissive Solaris = ["solaris2"]@@ -180,11 +184,21 @@ instance Text Platform where disp (Platform arch os) = disp arch <> Disp.char '-' <> disp os+ -- TODO: there are ambigious platforms like: `arch-word-os`+ -- which could be parsed as+ -- * Platform "arch-word" "os"+ -- * Platform "arch" "word-os"+ -- We could support that preferring variants 'OtherOS' or 'OtherArch'+ --+ -- For now we split into arch and os parts on the first dash. parse = do- arch <- parse+ arch <- parseDashlessArch _ <- Parse.char '-' os <- parse return (Platform arch os)+ where+ parseDashlessArch :: Parse.ReadP r Arch+ parseDashlessArch = fmap (classifyArch Strict) dashlessIdent -- | The platform Cabal was compiled on. In most cases, -- @LocalBuildInfo.hostPlatform@ should be used instead (the platform we're@@ -195,9 +209,15 @@ -- Utils: ident :: Parse.ReadP r String-ident = Parse.munch1 (\c -> Char.isAlphaNum c || c == '_' || c == '-')- --TODO: probably should disallow starting with a number+ident = liftM2 (:) first rest+ where first = Parse.satisfy Char.isAlpha+ rest = Parse.munch (\c -> Char.isAlphaNum c || c == '_' || c == '-') +dashlessIdent :: Parse.ReadP r String+dashlessIdent = liftM2 (:) first rest+ where first = Parse.satisfy Char.isAlpha+ rest = Parse.munch (\c -> Char.isAlphaNum c || c == '_')+ lowercase :: String -> String lowercase = map Char.toLower @@ -206,10 +226,10 @@ fmap fst (listToMaybe $ Parse.readP_to_S parseTriple triple) where parseWord = Parse.munch1 (\c -> Char.isAlphaNum c || c == '_') parseTriple = do- arch <- fmap (classifyArch Strict) parseWord+ arch <- fmap (classifyArch Permissive) parseWord _ <- Parse.char '-' _ <- parseWord -- Skip vendor _ <- Parse.char '-'- os <- fmap (classifyOS Compat) ident -- OS may have hyphens, like+ os <- fmap (classifyOS Permissive) ident -- OS may have hyphens, like -- 'nto-qnx' return $ Platform arch os
Distribution/Text.hs view
@@ -13,6 +13,7 @@ -- module Distribution.Text ( Text(..),+ defaultStyle, display, simpleParse, ) where@@ -27,13 +28,15 @@ disp :: a -> Disp.Doc parse :: Parse.ReadP r a +-- | The default rendering style used in Cabal for console output.+defaultStyle :: Disp.Style+defaultStyle = Disp.Style { Disp.mode = Disp.PageMode+ , Disp.lineLength = 79+ , Disp.ribbonsPerLine = 1.0+ }+ display :: Text a => a -> String-display = Disp.renderStyle style . disp- where style = Disp.Style {- Disp.mode = Disp.PageMode,- Disp.lineLength = 79,- Disp.ribbonsPerLine = 1.0- }+display = Disp.renderStyle defaultStyle . disp simpleParse :: Text a => String -> Maybe a simpleParse str = case [ p | (p, s) <- Parse.readP_to_S parse str@@ -51,18 +54,20 @@ , (Parse.string "False" Parse.+++ Parse.string "false") >> return False ] +instance Text Int where+ disp = Disp.text . show+ parse = (fmap negate $ Parse.char '-' >> parseNat) Parse.+++ parseNat++-- | Parser for non-negative integers.+parseNat :: Parse.ReadP r Int+parseNat = read `fmap` Parse.munch1 Char.isDigit+ instance Text Version where disp (Version branch _tags) -- Death to version tags!! = Disp.hcat (Disp.punctuate (Disp.char '.') (map Disp.int branch)) parse = do- branch <- Parse.sepBy1 digits (Parse.char '.')- tags <- Parse.many (Parse.char '-' >> Parse.munch1 Char.isAlphaNum)- return (Version branch tags) --TODO: should we ignore the tags?- where- digits = do- first <- Parse.satisfy Char.isDigit- if first == '0'- then return 0- else do rest <- Parse.munch Char.isDigit- return (read (first : rest))+ branch <- Parse.sepBy1 parseNat (Parse.char '.')+ -- allow but ignore tags:+ _tags <- Parse.many (Parse.char '-' >> Parse.munch1 Char.isAlphaNum)+ return (Version branch [])
Distribution/Utils/NubList.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} module Distribution.Utils.NubList ( NubList -- opaque , toNubList -- smart construtor@@ -11,12 +10,9 @@ , overNubListR ) where +import Distribution.Compat.Semigroup as Semi import Distribution.Compat.Binary-#if __GLASGOW_HASKELL__ < 710-import Data.Monoid-#endif--import Distribution.Simple.Utils (ordNub, listUnion, ordNubRight, listUnionRight)+import Distribution.Simple.Utils import qualified Text.Read as R @@ -54,8 +50,11 @@ instance Ord a => Monoid (NubList a) where mempty = NubList []- mappend (NubList xs) (NubList ys) = NubList $ xs `listUnion` ys+ mappend = (Semi.<>) +instance Ord a => Semigroup (NubList a) where+ (NubList xs) <> (NubList ys) = NubList $ xs `listUnion` ys+ instance Show a => Show (NubList a) where show (NubList list) = show list @@ -63,7 +62,7 @@ readPrec = readNubList toNubList -- | Helper used by NubList/NubListR's Read instances.-readNubList :: (Ord a, Read a) => ([a] -> l a) -> R.ReadPrec (l a)+readNubList :: (Read a) => ([a] -> l a) -> R.ReadPrec (l a) readNubList toList = R.parens . R.prec 10 $ fmap toList R.readPrec -- | Binary instance for 'NubList a' is the same as for '[a]'. For 'put', we@@ -91,7 +90,10 @@ instance Ord a => Monoid (NubListR a) where mempty = NubListR []- mappend (NubListR xs) (NubListR ys) = NubListR $ xs `listUnionRight` ys+ mappend = (Semi.<>)++instance Ord a => Semigroup (NubListR a) where+ (NubListR xs) <> (NubListR ys) = NubListR $ xs `listUnionRight` ys instance Show a => Show (NubListR a) where show (NubListR list) = show list
Distribution/Verbosity.hs view
@@ -24,9 +24,10 @@ showForCabal, showForGHC ) where -import Distribution.Compat.Binary (Binary)-import Data.List (elemIndex)+import Distribution.Compat.Binary import Distribution.ReadE++import Data.List (elemIndex) import GHC.Generics data Verbosity = Silent | Normal | Verbose | Deafening
Distribution/Version.hs view
@@ -4,20 +4,23 @@ {-# LANGUAGE StandaloneDeriving #-} #endif --- Hack approach to support bootstrapping--- Assume binary <0.8 when MIN_VERSION_binary macro is not available.--- Starting with GHC>=8.0, compiler will hopefully provide this macros too.--- https://ghc.haskell.org/trac/ghc/ticket/10970------ Otherwise, one can specify -DMIN_VERSION_binary_0_8_0=1, when bootstrapping--- with binary >=0.8.0.0+-- Hack approach to support bootstrapping.+-- When MIN_VERSION_binary macro is available, use it. But it's not available+-- during bootstrapping (or anyone else building Setup.hs directly). If the+-- builder specifies -DMIN_VERSION_binary_0_8_0=1 or =0 then we respect that.+-- Otherwise we pick a default based on GHC version: assume binary <0.8 when+-- GHC < 8.0, and binary >=0.8 when GHC >= 8.0. #ifdef MIN_VERSION_binary #define MIN_VERSION_binary_0_8_0 MIN_VERSION_binary(0,8,0) #else #ifndef MIN_VERSION_binary_0_8_0+#if __GLASGOW_HASKELL__ >= 800+#define MIN_VERSION_binary_0_8_0 1+#else #define MIN_VERSION_binary_0_8_0 0 #endif #endif+#endif #if !MIN_VERSION_binary_0_8_0 {-# OPTIONS_GHC -fno-warn-orphans #-}@@ -50,6 +53,7 @@ laterVersion, earlierVersion, orLaterVersion, orEarlierVersion, unionVersionRanges, intersectVersionRanges,+ invertVersionRange, withinVersion, betweenVersionsInclusive, @@ -61,6 +65,8 @@ simplifyVersionRange, foldVersionRange, foldVersionRange',+ hasUpperBound,+ hasLowerBound, -- ** Modification removeUpperBound,@@ -86,6 +92,7 @@ mkVersionIntervals, unionVersionIntervals, intersectVersionIntervals,+ invertVersionIntervals ) where @@ -95,9 +102,10 @@ import Data.Version ( Version(..) ) import GHC.Generics ( Generic ) -import Distribution.Text ( Text(..) )+import Distribution.Text import qualified Distribution.Compat.ReadP as Parse-import Distribution.Compat.ReadP ((+++))+import Distribution.Compat.ReadP hiding (get)+ import qualified Text.PrettyPrint as Disp import Text.PrettyPrint ((<>), (<+>)) import qualified Data.Char as Char (isDigit)@@ -140,13 +148,20 @@ put (Version br tags) = put br >> put tags #endif -{-# DEPRECATED AnyVersion "Use 'anyVersion', 'foldVersionRange' or 'asVersionIntervals'" #-}-{-# DEPRECATED ThisVersion "use 'thisVersion', 'foldVersionRange' or 'asVersionIntervals'" #-}-{-# DEPRECATED LaterVersion "use 'laterVersion', 'foldVersionRange' or 'asVersionIntervals'" #-}-{-# DEPRECATED EarlierVersion "use 'earlierVersion', 'foldVersionRange' or 'asVersionIntervals'" #-}-{-# DEPRECATED WildcardVersion "use 'anyVersion', 'foldVersionRange' or 'asVersionIntervals'" #-}-{-# DEPRECATED UnionVersionRanges "use 'unionVersionRanges', 'foldVersionRange' or 'asVersionIntervals'" #-}-{-# DEPRECATED IntersectVersionRanges "use 'intersectVersionRanges', 'foldVersionRange' or 'asVersionIntervals'" #-}+{-# DeprecateD AnyVersion+ "Use 'anyVersion', 'foldVersionRange' or 'asVersionIntervals'" #-}+{-# DEPRECATED ThisVersion+ "Use 'thisVersion', 'foldVersionRange' or 'asVersionIntervals'" #-}+{-# DEPRECATED LaterVersion+ "Use 'laterVersion', 'foldVersionRange' or 'asVersionIntervals'" #-}+{-# DEPRECATED EarlierVersion+ "Use 'earlierVersion', 'foldVersionRange' or 'asVersionIntervals'" #-}+{-# DEPRECATED WildcardVersion+ "Use 'anyVersion', 'foldVersionRange' or 'asVersionIntervals'" #-}+{-# DEPRECATED UnionVersionRanges+ "Use 'unionVersionRanges', 'foldVersionRange' or 'asVersionIntervals'" #-}+{-# DEPRECATED IntersectVersionRanges+ "Use 'intersectVersionRanges', 'foldVersionRange' or 'asVersionIntervals'"#-} -- | The version range @-any@. That is, a version range containing all -- versions.@@ -225,6 +240,16 @@ intersectVersionRanges :: VersionRange -> VersionRange -> VersionRange intersectVersionRanges = IntersectVersionRanges +-- | The inverse of a version range+--+-- > withinRange v' (invertVersionRange vr)+-- > = not (withinRange v' vr)+--+invertVersionRange :: VersionRange -> VersionRange+invertVersionRange =+ fromVersionIntervals . invertVersionIntervals+ . VersionIntervals . asVersionIntervals+ -- | The version range @== v.*@. -- -- For example, for version @1.2@, the version range @== 1.2.*@ is the same as@@ -293,9 +318,10 @@ (orLaterVersion v) (earlierVersion (wildcardUpperBound v)) --- | An extended variant of 'foldVersionRange' that also provides a view of--- in which the syntactic sugar @\">= v\"@, @\"<= v\"@ and @\"== v.*\"@ is presented--- explicitly rather than in terms of the other basic syntax.+-- | An extended variant of 'foldVersionRange' that also provides a view of the+-- expression in which the syntactic sugar @\">= v\"@, @\"<= v\"@ and @\"==+-- v.*\"@ is presented explicitly rather than in terms of the other basic+-- syntax. -- foldVersionRange' :: a -- ^ @\"-any\"@ version -> (Version -> a) -- ^ @\"== v\"@@@ -697,6 +723,47 @@ where lowerBound = max lower lower' +invertVersionIntervals :: VersionIntervals+ -> VersionIntervals+invertVersionIntervals (VersionIntervals xs) =+ case xs of+ -- Empty interval set+ [] -> VersionIntervals [(noLowerBound, NoUpperBound)]+ -- Interval with no lower bound+ ((lb, ub) : more) | lb == noLowerBound ->+ VersionIntervals $ invertVersionIntervals' ub more+ -- Interval with a lower bound+ ((lb, ub) : more) ->+ VersionIntervals $ (noLowerBound, invertLowerBound lb)+ : invertVersionIntervals' ub more+ where+ -- Invert subsequent version intervals given the upper bound of+ -- the intervals already inverted.+ invertVersionIntervals' :: UpperBound+ -> [(LowerBound, UpperBound)]+ -> [(LowerBound, UpperBound)]+ invertVersionIntervals' NoUpperBound [] = []+ invertVersionIntervals' ub0 [] = [(invertUpperBound ub0, NoUpperBound)]+ invertVersionIntervals' ub0 [(lb, NoUpperBound)] =+ [(invertUpperBound ub0, invertLowerBound lb)]+ invertVersionIntervals' ub0 ((lb, ub1) : more) =+ (invertUpperBound ub0, invertLowerBound lb)+ : invertVersionIntervals' ub1 more++ invertLowerBound :: LowerBound -> UpperBound+ invertLowerBound (LowerBound v b) = UpperBound v (invertBound b)++ invertUpperBound :: UpperBound -> LowerBound+ invertUpperBound (UpperBound v b) = LowerBound v (invertBound b)+ invertUpperBound NoUpperBound = error "NoUpperBound: unexpected"++ invertBound :: Bound -> Bound+ invertBound ExclusiveBound = InclusiveBound+ invertBound InclusiveBound = ExclusiveBound++ noLowerBound :: LowerBound+ noLowerBound = LowerBound (Version [0] []) InclusiveBound+ ------------------------------- -- Parsing and pretty printing --@@ -711,9 +778,11 @@ (\v -> (Disp.text ">=" <> disp v , 0)) (\v -> (Disp.text "<=" <> disp v , 0)) (\v _ -> (Disp.text "==" <> dispWild v , 0))- (\(r1, p1) (r2, p2) -> (punct 2 p1 r1 <+> Disp.text "||" <+> punct 2 p2 r2 , 2))- (\(r1, p1) (r2, p2) -> (punct 1 p1 r1 <+> Disp.text "&&" <+> punct 1 p2 r2 , 1))- (\(r, p) -> (Disp.parens r, p))+ (\(r1, p1) (r2, p2) ->+ (punct 2 p1 r1 <+> Disp.text "||" <+> punct 2 p2 r2 , 2))+ (\(r1, p1) (r2, p2) ->+ (punct 1 p1 r1 <+> Disp.text "&&" <+> punct 1 p2 r2 , 1))+ (\(r, _) -> (Disp.parens r, 0)) where dispWild (Version b _) = Disp.hcat (Disp.punctuate (Disp.char '.') (map Disp.int b))@@ -775,3 +844,28 @@ (">", LaterVersion), (">=", orLaterVersion), ("==", ThisVersion) ]++-- | Does the version range have an upper bound?+--+-- @since 1.24.0.0+hasUpperBound :: VersionRange -> Bool+hasUpperBound = foldVersionRange+ False+ (const True)+ (const False)+ (const True)+ (&&) (||)++-- | Does the version range have an explicit lower bound?+--+-- Note: this function only considers the user-specified lower bounds, but not+-- the implicit >=0 lower bound.+--+-- @since 1.24.0.0+hasLowerBound :: VersionRange -> Bool+hasLowerBound = foldVersionRange+ False+ (const True)+ (const True)+ (const False)+ (&&) (||)
Language/Haskell/Extension.hs view
@@ -22,12 +22,13 @@ deprecatedExtensions ) where -import Distribution.Text (Text(..))+import Distribution.Text import qualified Distribution.Compat.ReadP as Parse+import Distribution.Compat.Binary+ import qualified Text.PrettyPrint as Disp import qualified Data.Char as Char (isAlphaNum) import Data.Array (Array, accumArray, bounds, Ix(inRange), (!))-import Distribution.Compat.Binary (Binary) import Data.Data (Data) import Data.Typeable (Typeable) import GHC.Generics (Generic)@@ -713,6 +714,57 @@ -- -- * <http://www.haskell.org/ghc/docs/latest/html/users_guide/other-type-extensions.html#derive-any-class> | DeriveAnyClass++ -- | Enable @deriving@ for the 'Language.Haskell.TH.Syntax.Lift' class.+ --+ -- * <http://www.haskell.org/ghc/docs/latest/html/users_guide/deriving.html#deriving-lift>+ | DeriveLift++ -- | Enable support for 'static pointers' (and the @static@+ -- keyword) to refer to globally stable names, even across+ -- different programs.+ --+ -- * <http://www.haskell.org/ghc/docs/latest/html/users_guide/static-pointers.html>+ | StaticPointers++ -- | Switches data type declarations to be strict by default (as if+ -- they had a bang using @BangPatterns@), and allow opt-in field+ -- laziness using @~@.+ | StrictData++ -- | Switches all pattern bindings to be strict by default (as if+ -- they had a bang using @BangPatterns@), ordinary patterns are+ -- recovered using @~@. Implies @StrictData@.+ | Strict++ -- | Allows @do@-notation for types that are @'Applicative'@ as well+ -- as @'Monad'@. When enabled, desugaring @do@ notation tries to use+ -- @(<*>)@ and @'fmap'@ and @'join'@ as far as possible.+ | ApplicativeDo++ -- | Allow records to use duplicated field labels for accessors.+ | DuplicateRecordFields++ -- | Enable explicit type applications with the syntax @id \@Int@.+ | TypeApplications++ -- | Dissolve the distinction between types and kinds, allowing the compiler+ -- to reason about kind equality and therefore enabling GADTs to be promoted+ -- to the type-level.+ | TypeInType++ -- | Allow recursive (and therefore undecideable) super-class relationships.+ | UndecidableSuperClasses++ -- | A temporary extension to help library authors check if their+ -- code will compile with the new planned desugaring of fail.+ | MonadFailDesugaring++ -- | A subset of @TemplateHaskell@ including only quasi-quoting.+ | TemplateHaskellQuotes++ -- | Allows use of the @#label@ syntax.+ | OverloadedLabels deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable, Data)
Setup.hs view
@@ -8,3 +8,6 @@ -- on any previous installation. This also means we can use any new features -- immediately because we never have to worry about building Cabal with an -- older version of itself.+--+-- NOTE 25/01/2015: Bootstrapping is disabled for now, see+-- https://github.com/haskell/cabal/issues/3003.
changelog view
@@ -1,42 +1,32 @@-1.22.8.0 Ryan Thomas <ryan@ryant.org> March 2016- * Distribution.Simple.Setup: remove job cap. Fixes #3191.- * Check all object file suffixes for recompilation. Fixes #3128.- * Move source files under 'src/'. Fixes #3003.--1.22.7.0 Ryan Thomas <ryan@ryant.org> January 2016- * Backport #3012 to the 1.22 branch- * Cabal.cabal: change build-type to Simple- * Add foldl' import- * The Cabal part for fully gcc-like response files--1.22.6.0- * Relax upper bound to allow upcoming binary-0.8--1.22.5.0- * Don't recompile C sources unless needed (#2601). (Luke Iannini)- * Support Haddock response files.- * Add frameworks when linking a dynamic library.--1.22.4.0 Ryan Thomas <ryan@ryant.org> June 2015- * Add libname install-dirs variable, use it by default. Fixes #2437. (Edward Z. Yang)- * Reduce temporary directory name length, fixes #2502. (Edward Z. Yang)- * Workaround for #2527. (Mikhail Glushenkov)--1.22.3.0 Ryan Thomas <ryan@ryant.org> April 2015- * Fix for the ghcjs-pkg version number handling (Luite Stegeman)- * filterConfigureFlags: filter more flags (Mikhail Glushenkov)- * Cabal check will fail on -fprof-auto passed as a ghc-option - Fixes #2479 (John Chee)+-*-change-log-*- -1.22.2.0 Ryan Thomas <ryan@ryant.org> March 2015- * Don't pass '--{en,dis}able-profiling' to old setup.- * Add -Wall police- * Fix dependencies on 'old-time'- * Fix test interface detailed-0.9 with GHC 7.10- * Fix HPC tests with GHC 7.10- * Make sure to pass the package key to ghc- * Use --package-{name|version} when available for Haddock when available- * Put full package name and version in library names- * Fully specify package key format, so external tools can generate it.+1.24.0.0 Ryan Thomas <ryan@ryant.org> May 2016+ * Support GHC 8.+ * Deal with extra C sources from preprocessors (#238).+ * Include cabal_macros.h when running c2hs (#2600).+ * Don't recompile C sources unless needed (#2601).+ * Read 'builddir' option from 'CABAL_BUILDDIR' environment variable+ * Add '--profiling-detail=$level' flag with a default for libraries+ and executables of 'exported-functions' and 'toplevel-functions'+ respetively (GHC's '-fprof-auto-{exported,top}' flags) (#193).+ * New 'custom-setup' stanza to specify setup deps. Setup is also built+ with the cabal_macros.h style macros, for conditional compilation.+ * Support Haddock response files (#2746).+ * Fixed a bug in the Text instance for Platform (#2862).+ * New 'setup haddock' option: '--for-hackage' (#2852).+ * New --show-detail=direct; like streaming, but allows the test+ program to detect that is connected to a terminal, and works+ reliable with a non-threaded runtime (#2911, and serves as a+ work-around for #2398)+ * Library support for multi-instance package DBs (#2948).+ * Improved the './Setup configure' solver (#3082, #3076).+ * The '--allow-newer' option can be now used with './Setup+ configure' (#3163).+ * Added a way to specify extra locations to find OS X frameworks+ in ('extra-framework-dirs'). Can be used both in .cabal files and+ as an argument to './Setup configure' (#3158).+ * Macros 'VERSION_$pkgname' and 'MIN_VERSION_$pkgname' are now+ also generated for the current package. (#3235). 1.22.0.0 Johan Tibell <johan.tibell@gmail.com> January 2015 * Support GHC 7.10.
+ doc/Cabal.css view
@@ -0,0 +1,49 @@+body {+ max-width: 18cm;+}++div {+ font-family: sans-serif;+ color: black;+ background: white+}++h1, h2, h3, h4, h5, h6, p.title { color: #005A9C }++h1 { font: 170% sans-serif }+h2 { font: 140% sans-serif }+h3 { font: 120% sans-serif }+h4 { font: bold 100% sans-serif }+h5 { font: italic 100% sans-serif }+h6 { font: small-caps 100% sans-serif }++pre {+ font-family: monospace;+ border-width: 1px;+ border-style: solid;+ padding: 0.3em+}++pre.screen { color: #006400 }+pre.programlisting { color: maroon }++div.example {+ margin: 1ex 0em;+ border: solid #412e25 1px;+ padding: 0ex 0.4em+}++div.example, div.example-contents {+ background-color: #fffcf5+}++a:link { color: #0000C8 }+a:hover { background: #FFFFA8 }+a:active { color: #D00000 }+a:visited { color: #680098 }++h1 a:link, h2 a:link, h3 a:link, h4 a:link, h5 a:link, h6 a:link,+h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited {+ color: #005A9C;+ text-decoration: none+}
doc/developing-packages.markdown view
@@ -676,10 +676,11 @@ The syntax of the value depends on the field. Field types include: _token_, _filename_, _directory_-: Either a sequence of one or more non-space non-comma characters, or- a quoted string in Haskell 98 lexical syntax. Unless otherwise- stated, relative filenames and directories are interpreted from the- package root directory.+: Either a sequence of one or more non-space non-comma characters, or a quoted+ string in Haskell 98 lexical syntax. The latter can be used for escaping+ whitespace, for example: `ghc-options: -Wall "-with-rtsopts=-T -I1"`.+ Unless otherwise stated, relative filenames and directories are interpreted+ from the package root directory. _freeform_, _URL_, _address_ : An arbitrary, uninterpreted string.@@ -705,8 +706,12 @@ * `.x` ([alex][]) * `.cpphs` ([cpphs][]) -When building, Cabal will automatically run the appropriate preprocessor-and compile the Haskell module it produces.+When building, Cabal will automatically run the appropriate+preprocessor and compile the Haskell module it produces. For the+`c2hs` and `hsc2hs` preprocessors, Cabal will also automatically add,+compile and link any C sources generated by the preprocessor (produced+by `hsc2hs`'s `#def` feature or `c2hs`'s auto-generated wrapper+functions). Some fields take lists of values, which are optionally separated by commas, except for the `build-depends` field, where the commas are mandatory.@@ -998,6 +1003,32 @@ `cabal.config` file. All environments which share this file will use the dependency versions specified in it. +#### Generating dependency version bounds ####++Cabal also has the ability to suggest dependency version bounds that conform to+[Package Versioning Policy][PVP], which is a recommended versioning system for+publicly released Cabal packages. This is done by running the `gen-bounds`+command:++~~~~~~~~~~~~~~~~+cabal gen-bounds+~~~~~~~~~~~~~~~~++For example, given the following dependencies specified in `build-depends`:++~~~~~~~~~~~~~~~~+foo == 0.5.2+bar == 1.1+~~~~~~~~~~~~~~~~++`gen-bounds` will suggest changing them to the following:++~~~~~~~~~~~~~~~~+foo >= 0.5.2 && < 0.6+bar >= 1.1 && < 1.2+~~~~~~~~~~~~~~~~++ ### Executables ### Executable sections (if present) describe executable programs contained@@ -1077,9 +1108,7 @@ #### Example: Package using `exitcode-stdio-1.0` interface #### The example package description and executable source file below demonstrate-the use of the `exitcode-stdio-1.0` interface. For brevity, the example package-does not include a library or any normal executables, but a real package would-be required to have at least one library or executable.+the use of the `exitcode-stdio-1.0` interface. foo.cabal: @@ -1111,12 +1140,10 @@ #### Example: Package using `detailed-0.9` interface #### The example package description and test module source file below demonstrate-the use of the `detailed-0.9` interface. For brevity, the example package does-note include a library or any normal executables, but a real package would be-required to have at least one library or executable. The test module below-also develops a simple implementation of the interface set by-`Distribution.TestSuite`, but in actual usage the implementation would be-provided by the library that provides the testing facility.+the use of the `detailed-0.9` interface. The test module also develops a simple+implementation of the interface set by `Distribution.TestSuite`, but in actual+usage the implementation would be provided by the library that provides the+testing facility. bar.cabal: @@ -1204,9 +1231,7 @@ #### Example: Package using `exitcode-stdio-1.0` interface #### The example package description and executable source file below demonstrate-the use of the `exitcode-stdio-1.0` interface. For brevity, the example package-does not include a library or any normal executables, but a real package would-be required to have at least one library or executable.+the use of the `exitcode-stdio-1.0` interface. foo.cabal: @@ -1257,12 +1282,12 @@ ### Build information ### -The following fields may be optionally present in a library or-executable section, and give information for the building of the+The following fields may be optionally present in a library, executable, test+suite or benchmark section, and give information for the building of the corresponding library or executable. See also the sections on [system-dependent parameters](#system-dependent-parameters) and-[configurations](#configurations) for a way to supply system-dependent-values for these fields.+[configurations](#configurations) for a way to supply system-dependent values+for these fields. `build-depends:` _package list_ : A list of packages needed to build this one. Each package can be@@ -1292,29 +1317,16 @@ It is only syntactic sugar. It is exactly equivalent to `foo >= 1.2 && < 1.3`. - With Cabal 1.20 and GHC 7.10, `build-depends` also supports module- thinning and renaming, which allows you to selectively decide what- modules become visible from a package dependency. For example:-- ~~~~~~~~~~~~~~~~- build-depends: containers (Data.Set, Data.IntMap as Map)- ~~~~~~~~~~~~~~~~-- This results in only the modules `Data.Set` and `Map` being visible to- the user from containers, hiding all other modules. To add additional- names for modules without hiding the others, you can use the `with`- keyword:-- ~~~~~~~~~~~~~~~~- build-depends: containers with (Data.IntMap as Map)- ~~~~~~~~~~~~~~~~- Note: Prior to Cabal 1.8, build-depends specified in each section were global to all sections. This was unintentional, but some packages were written to depend on it, so if you need your build-depends to be local to each section, you must specify at least `Cabal-Version: >= 1.8` in your `.cabal` file. + Note: Cabal 1.20 experimentally supported module thinning and+ renaming in `build-depends`; however, this support has since been+ removed and should not be used.+ `other-modules:` _identifier list_ : A list of modules used by the component but not exposed to users. For a library component, these would be hidden modules of the@@ -1330,21 +1342,38 @@ For backwards compatibility, the old variant `hs-source-dir` is also recognized. -`extensions:` _identifier list_-: A list of Haskell extensions used by every module. Extension names- are the constructors of the [Extension][extension] type. These- determine corresponding compiler options. In particular, `CPP` specifies that- Haskell source files are to be preprocessed with a C preprocessor.+`default-extensions:` _identifier list_+: A list of Haskell extensions used by every module. These determine+ corresponding compiler options enabled for all files. Extension names are+ the constructors of the [Extension][extension] type. For example, `CPP`+ specifies that Haskell source files are to be preprocessed with a C+ preprocessor. - Extensions used only by one module may be specified by placing a- `LANGUAGE` pragma in the source file affected, e.g.:+`other-extensions:` _identifier list_+: A list of Haskell extensions used by some (but not necessarily all) modules.+ From GHC version 6.6 onward, these may be specified by placing a `LANGUAGE`+ pragma in the source files affected e.g. ~~~~~~~~~~~~~~~~ {-# LANGUAGE CPP, MultiParamTypeClasses #-} ~~~~~~~~~~~~~~~~ - Note: GHC versions prior to 6.6 do not support the `LANGUAGE` pragma.+ In Cabal-1.24 the dependency solver will use this and `default-extensions` information.+ Cabal prior to 1.24 will abort compilation if the current compiler doesn't provide+ the extensions. + If you use some extensions conditionally, using CPP or conditional module lists,+ it is good to replicate the condition in `other-extensions` declarations:++ ~~~~~~~~~~~~~~~~+ other-extensions: CPP+ if impl(ghc >= 7.5)+ other-extensions: PolyKinds+ ~~~~~~~~~~~~~~~~++ You could also omit the conditionally used extensions, as they are for information only,+ but it is recommended to replicate them in `other-extensions` declarations.+ `build-tools:` _program list_ : A list of programs, possibly annotated with versions, needed to build this package, e.g. `c2hs >= 0.15, cpphs`.If no version@@ -1363,12 +1392,33 @@ Options required only by one module may be specified by placing an `OPTIONS_GHC` pragma in the source file affected. + As with many other fields, whitespace can be escaped by using Haskell string+ syntax. Example: `ghc-options: -Wcompat "-with-rtsopts=-T -I1" -Wall`.+ `ghc-prof-options:` _token list_ : Additional options for GHC when the package is built with profiling enabled. + Note that as of Cabal-1.24, the default profiling detail level defaults to+ `exported-functions` for libraries and `toplevel-functions` for+ executables. For GHC these correspond to the flags `-fprof-auto-exported`+ and `-fprof-auto-top`. Prior to Cabal-1.24 the level defaulted to `none`.+ These levels can be adjusted by the person building the package with the+ `--profiling-detail` and `--library-profiling-detail` flags.++ It is typically better for the person building the package to pick the+ profiling detail level rather than for the package author. So unless you+ have special needs it is probably better not to specify any of the GHC+ `-fprof-auto*` flags here. However if you wish to override the profiling+ detail level, you can do so using the `ghc-prof-options` field: use+ `-fno-prof-auto` or one of the other `-fprof-auto*` flags.++ `ghc-shared-options:` _token list_ : Additional options for GHC when the package is built as shared library.+ The options specified via this field are combined with the ones specified+ via `ghc-options`, and are passed to GHC during both the compile and+ link phases. `includes:` _filename list_ : A list of header files to be included in any compilations via C.@@ -1430,7 +1480,7 @@ parameters](#system-dependent-parameters)>. `pkgconfig-depends:` _package list_-: A list of [pkg-config][] packages, needed to build this package.+: A list of [pkg-config] packages, needed to build this package. They can be annotated with versions, e.g. `gtk+-2.0 >= 2.10, cairo >= 1.0`. If no version constraint is specified, any version is assumed to be acceptable. Cabal uses `pkg-config` to find if the@@ -1447,6 +1497,10 @@ developer documentation for more details on frameworks. This entry is ignored on all other platforms. +`extra-frameworks-dirs:` _directory list_+: On Darwin/MacOS X, a list of directories to search for frameworks.+ This entry is ignored on all other platforms.+ ### Configurations ### Library and executable sections may include conditional@@ -1687,15 +1741,15 @@ items, for example ~~~~~~~~~~~~~~~~- Extensions: CPP+ other-extensions: CPP if impl(ghc)- Extensions: MultiParamTypeClasses+ other-extensions: MultiParamTypeClasses ~~~~~~~~~~~~~~~~ when compiled using GHC will be combined to ~~~~~~~~~~~~~~~~- Extensions: CPP, MultiParamTypeClasses+ other-extensions: CPP, MultiParamTypeClasses ~~~~~~~~~~~~~~~~ Similarly, if two conditional sections appear at the same nesting@@ -1872,6 +1926,21 @@ The `Paths_`_pkgname_ module is not platform independent so it does not get included in the source tarballs generated by `sdist`. +The `Paths_`_pkgname_ module also includes some other useful functions+and values, which record the version of the package and some other+directories which the package has been configured to be installed+into (e.g. data files live in `getDataDir`):++~~~~~~~~~~~~~~~+version :: Version++getBinDir :: IO FilePath+getLibDir :: IO FilePath+getDataDir :: IO FilePath+getLibexecDir :: IO FilePath+getSysconfDir :: IO FilePath+~~~~~~~~~~~~~~~+ ### Accessing the package version ### The aforementioned auto generated `Paths_`_pkgname_ module also@@ -2144,3 +2213,4 @@ [Hackage]: http://hackage.haskell.org/ [pkg-config]: http://www.freedesktop.org/wiki/Software/pkg-config/ [REPL]: http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop+[PVP]: https://wiki.haskell.org/Package_versioning_policy
doc/index.markdown view
@@ -1,4 +1,5 @@ % Cabal User Guide+**Version: 1.24.0.0** Cabal is the standard package system for [Haskell] software. It helps people to configure, build and install Haskell software and to
doc/installing-packages.markdown view
@@ -1,5 +1,140 @@ % Cabal User Guide +# Configuration #++## Overview ##++The global configuration file for `cabal-install` is `~/.cabal/config`. If you+do not have this file, `cabal` will create it for you on the first call to+`cabal update`. Alternatively, you can explicitly ask `cabal` to create it for+you using++> `cabal user-config update`++Most of the options in this configuration file are also available as command+line arguments, and the corresponding documentation can be used to lookup their+meaning. The created configuration file only specifies values for a handful of+options. Most options are left at their default value, which it documents;+for instance,++~~~~~~~~~~~~~~~~+-- executable-stripping: True+~~~~~~~~~~~~~~~~++means that the configuration file currently does not specify a value for the+`executable-stripping` option (the line is commented out), and that the default+is `True`; if you wanted to disable stripping of executables by default, you+would change this line to++~~~~~~~~~~~~~~~~+executable-stripping: False+~~~~~~~~~~~~~~~~++You can also use `cabal user-config update` to migrate configuration files+created by older versions of `cabal`.++## Repository specification ##++An important part of the configuration if the specification of the repository.+When `cabal` creates a default config file, it configures the repository to+be the central Hackage server:++~~~~~~~~~~~~~~~~+repository hackage.haskell.org+ url: http://hackage.haskell.org/+~~~~~~~~~~~~~~~~++The name of the repository is given on the first line, and can be anything;+packages downloaded from this repository will be cached under+`~/.cabal/packages/hackage.haskell.org` (or whatever name you specify; you can+change the prefix by changing the value of `remote-repo-cache`). If you want,+you can configure multiple repositories, and `cabal` will combine them and be+able to download packages from any of them.++### Using secure repositories ###++For repositories that support the TUF security infrastructure (this includes+Hackage), you can enable secure access to the repository by specifying:++~~~~~~~~~~~~~~~~+repository hackage.haskell.org+ url: http://hackage.haskell.org/+ secure: True+ root-keys: <root-key-IDs>+ key-threshold: <key-threshold>+~~~~~~~~~~~~~~~~++The `<root-key-IDs>` and `<key-threshold>` values are used for bootstrapping. As+part of the TUF infrastructure the repository will contain a file `root.json`+(for instance,+[http://hackage.haskell.org/root.json](http://hackage.haskell.org/root.json))+which the client needs to do verification. However, how can `cabal` verify the+`root.json` file _itself_? This is known as bootstrapping: if you specify a list+of root key IDs and a corresponding threshold, `cabal` will verify that the+downloaded `root.json` file has been signed with at least `<key-threshold>`+keys from your set of `<root-key-IDs>`.++You can, but are not recommended to, omit these two fields. In that case `cabal`+will download the `root.json` field and use it without verification. Although+this bootstrapping step is then unsafe, all subsequent access is secure+(provided that the downloaded `root.json` was not tempered with). Of course,+adding `root-keys` and `key-threshold` to your repository specification only+shifts the problem, because now you somehow need to make sure that the key IDs+you received were the right ones. How that is done is however outside the scope+of `cabal` proper.++More information about the security infrastructure can be found at+[https://github.com/well-typed/hackage-security](https://github.com/well-typed/hackage-security).++### Legacy repositories ###++Currently `cabal` supports two kinds of “legacy” repositories. The+first is specified using++~~~~~~~~~~~~~~~~+remote-repo: hackage.haskell.org:http://hackage.haskell.org/packages/archive+~~~~~~~~~~~~~~~~++This is just syntactic sugar for++~~~~~~~~~~~~~~~~+repository hackage.haskell.org+ url: hackage.haskell.org:http://hackage.haskell.org/packages/archive+~~~~~~~~~~~~~~~~++although, in (and only in) the specific case of Hackage, the URL+`http://hackage.haskell.org/packages/archive` will be silently translated to+`http://hackage.haskell.org/`.++The second kind of legacy repositories are so-called “local”+repositories:++~~~~~~~~~~~~~~~~+local-repo: my-local-repo:/path/to/local/repo+~~~~~~~~~~~~~~~~++This can be used to access repositories on the local file system. However, the+layout of these local repositories is different from the layout of remote+repositories, and usage of these local repositories is deprecated.++### Secure local repositories ###++If you want to use repositories on your local file system, it is recommended+instead to use a _secure_ local repository:++~~~~~~~~~~~~~~~~+repository my-local-repo+ url: file:/path/to/local/repo+ secure: True+ root-keys: <root-key-IDs>+ key-threshold: <key-threshold>+~~~~~~~~~~~~~~~~++The layout of these secure local repos matches the layout of remote repositories+exactly; the+[hackage-repo-tool](http://hackage.haskell.org/package/hackage-repo-tool) can be+used to create and manage such repositories.+ # Building and installing packages # After you've unpacked a Cabal package, you can build it by moving into@@ -610,6 +745,14 @@ be a file or directory. Not all implementations support arbitrary package databases. +`--default-user-config=` _file_+: Allows a "default" `cabal.config` freeze file to be passed in+ manually. This file will only be used if one does not exist in the+ project directory already. Typically, this can be set from the global+ cabal `config` file so as to provide a default set of partial+ constraints to be used by projects, providing a way for users to peg+ themselves to stable package collections.+ `--enable-optimization`[=_n_] or `-O`[_n_] : (default) Build with optimization flags (if available). This is appropriate for production use, taking more time to build faster@@ -626,25 +769,81 @@ : Build without optimization. This is suited for development: building will be quicker, but the resulting library or programs will be slower. +`--enable-profiling`+: Build libraries and executables with profiling enabled (for compilers+ that support profiling as a separate mode). For this to work, all+ libraries used by this package must also have been built with profiling+ support. For libraries this involves building an additional instance of+ the library in addition to the normal non-profiling instance. For+ executables it changes the single executable to be built in profiling mode.++ This flag covers both libraries and executables, but can be overridden+ by the `--enable-library-profiling` flag.++ See also the `--profiling-detail` flag below.++`--disable-profiling`+: (default) Do not enable profiling in generated libraries and executables.+ `--enable-library-profiling` or `-p`-: Request that an additional version of the library with profiling- features enabled be built and installed (only for implementations- that support profiling).+: As with `--enable-profiling` above, but it applies only for libraries. So+ this generates an additional profiling instance of the library in addition+ to the normal non-profiling instance. + The `--enable-profiling` flag controls the profiling mode for both+ libraries and executables, but if different modes are desired for+ libraries versus executables then use `--enable-library-profiling` as well.+ `--disable-library-profiling` : (default) Do not generate an additional profiling version of the library. -`--enable-profiling`-: Any executables generated should have profiling enabled (only for- implementations that support profiling). For this to work, all- libraries used by these executables must also have been built with- profiling support. The library will be built with profiling enabled (if- supported) unless `--disable-library-profiling` is specified.+`--profiling-detail`[=_level_]+: Some compilers that support profiling, notably GHC, can allocate costs to+ different parts of the program and there are different levels of+ granularity or detail with which this can be done. In particular for GHC+ this concept is called "cost centers", and GHC can automatically add cost+ centers, and can do so in different ways. -`--disable-profiling`-: (default) Do not enable profiling in generated executables.+ This flag covers both libraries and executables, but can be overridden+ by the `--library-profiling-detail` flag. + Currently this setting is ignored for compilers other than GHC. The levels+ that cabal currently supports are:++ `default`+ : For GHC this uses `exported-functions` for libraries and+ `toplevel-functions` for executables.++ `none`+ : No costs will be assigned to any code within this component.++ `exported-functions`+ : Costs will be assigned at the granularity of all top level functions+ exported from each module. In GHC specifically, this is for non-inline+ functions.++ `toplevel-functions`+ : Costs will be assigned at the granularity of all top level functions+ in each module, whether they are exported from the module or not.+ In GHC specifically, this is for non-inline functions.++ `all-functions`+ : Costs will be assigned at the granularity of all functions in each+ module, whether top level or local. In GHC specifically, this is for+ non-inline toplevel or where-bound functions or values.++ This flag is new in Cabal-1.24. Prior versions used the equivalent of+ `none` above.++`--library-profiling-detail`[=_level_]+: As with `--profiling-detail` above, but it applies only for libraries.++ The level for both libraries and executables is set by the+ `--profiling-detail` flag, but if different levels are desired for+ libraries versus executables then use `--library-profiling-detail` as well.++ `--enable-library-vanilla` : (default) Build ordinary libraries (as opposed to profiling libraries). This is independent of the `--enable-library-profiling`@@ -733,6 +932,10 @@ : An extra directory to search for system libraries files. You can use this flag multiple times to get a list of directories. +`--extra-framework-dirs`[=_dir_]+: An extra directory to search for frameworks (OS X only). You can use this+ flag multiple times to get a list of directories.+ You might need to use this flag if you have standard system libraries in a non-standard location that is not mentioned in the package's `.cabal` file. Using this option has the same affect as@@ -779,8 +982,26 @@ $ cabal install --allow-newer=bar --constraint="bar==2.1" foo ~~~~~~~~~~~~~~~~ - It's also possible to enable `--allow-newer` permanently by setting- `allow-newer: True` in the `~/.cabal/config` file.+ It's also possible to limit the scope of `--allow-newer` to single+ packages with the `--allow-newer=scope:dep` syntax. This means that the+ dependency on `dep` will be relaxed only for the package `scope`.++ Example:++ ~~~~~~~~~~~~~~~~+ # Relax upper bound in foo's dependency on base; also relax upper bound in+ # every package's dependency on lens.+ $ cabal install --allow-newer=foo:base,lens++ # Relax upper bounds in foo's dependency on base and bar's dependency+ # on time; also relax the upper bound in the dependency on lens specified by+ # any package.+ $ cabal install --allow-newer=foo:base,lens --allow-newer=bar:time+ ~~~~~~~~~~~~~~~~++ Finally, one can enable `--allow-newer` permanently by setting `allow-newer:+ True` in the `~/.cabal/config` file. Enabling 'allow-newer' selectively is+ also supported in the config file (`allow-newer: foo, bar, baz:base`). `--constraint=`_constraint_ : Restrict solutions involving a package to a given version range.
tests/PackageTests.hs view
@@ -6,167 +6,278 @@ module Main where -import PackageTests.BenchmarkExeV10.Check-import PackageTests.BenchmarkOptions.Check-import PackageTests.BenchmarkStanza.Check--- import PackageTests.BuildDeps.GlobalBuildDepsNotAdditive1.Check--- import PackageTests.BuildDeps.GlobalBuildDepsNotAdditive2.Check-import PackageTests.BuildDeps.InternalLibrary0.Check-import PackageTests.BuildDeps.InternalLibrary1.Check-import PackageTests.BuildDeps.InternalLibrary2.Check-import PackageTests.BuildDeps.InternalLibrary3.Check-import PackageTests.BuildDeps.InternalLibrary4.Check-import PackageTests.BuildDeps.SameDepsAllRound.Check-import PackageTests.BuildDeps.TargetSpecificDeps1.Check-import PackageTests.BuildDeps.TargetSpecificDeps2.Check-import PackageTests.BuildDeps.TargetSpecificDeps3.Check-import PackageTests.BuildTestSuiteDetailedV09.Check-import PackageTests.PackageTester (PackageSpec(..), compileSetup)-import PackageTests.PathsModule.Executable.Check-import PackageTests.PathsModule.Library.Check-import PackageTests.PreProcess.Check-import PackageTests.TemplateHaskell.Check-import PackageTests.CMain.Check-import PackageTests.DeterministicAr.Check-import PackageTests.EmptyLib.Check-import PackageTests.Haddock.Check-import PackageTests.TestOptions.Check-import PackageTests.TestStanza.Check-import PackageTests.TestSuiteExeV10.Check-import PackageTests.OrderFlags.Check-import PackageTests.ReexportedModules.Check+import PackageTests.Options+import PackageTests.PackageTester+import PackageTests.Tests import Distribution.Simple.Configure- ( ConfigStateFileError(..), getConfigStateFile )+ ( ConfigStateFileError(..), findDistPrefOrDefault, getConfigStateFile+ , interpretPackageDbFlags )+import Distribution.Simple.Compiler (PackageDB(..), PackageDBStack) import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..))-import Distribution.Simple.Program.Types (programPath)+import Distribution.Simple.Program.Types (Program(..), programPath, programVersion) import Distribution.Simple.Program.Builtin ( ghcProgram, ghcPkgProgram, haddockProgram ) import Distribution.Simple.Program.Db (requireProgram)+import Distribution.Simple.Setup (Flag(..), readPackageDbList, showPackageDbList) import Distribution.Simple.Utils (cabalVersion)-import Distribution.Text (display)-import Distribution.Verbosity (normal)-import Distribution.Version (Version(Version))+import Distribution.Text (display, simpleParse)+import Distribution.Verbosity (normal, flagToVerbosity)+import Distribution.ReadE (readEOrFail) -import Control.Exception (try, throw)+import Control.Exception+import Data.Proxy ( Proxy(..) )+import Distribution.Compat.Environment ( lookupEnv ) import System.Directory- ( getCurrentDirectory, setCurrentDirectory )-import System.FilePath ((</>))-import System.IO (BufferMode(NoBuffering), hSetBuffering, stdout)-import Test.Framework (Test, TestName, defaultMain, testGroup)-import Test.Framework.Providers.HUnit (hUnitTestToTests)-import qualified Test.HUnit as HUnit---hunit :: TestName -> HUnit.Test -> Test-hunit name test = testGroup name $ hUnitTestToTests test+import Test.Tasty+import Test.Tasty.Options+import Test.Tasty.Ingredients+import Data.Maybe -tests :: Version -> PackageSpec -> FilePath -> FilePath -> [Test]-tests version inplaceSpec ghcPath ghcPkgPath =- [ hunit "BuildDeps/SameDepsAllRound"- (PackageTests.BuildDeps.SameDepsAllRound.Check.suite ghcPath)- -- The two following tests were disabled by Johan Tibell as- -- they have been failing for a long time:- -- , hunit "BuildDeps/GlobalBuildDepsNotAdditive1/"- -- (PackageTests.BuildDeps.GlobalBuildDepsNotAdditive1.Check.suite ghcPath)- -- , hunit "BuildDeps/GlobalBuildDepsNotAdditive2/"- -- (PackageTests.BuildDeps.GlobalBuildDepsNotAdditive2.Check.suite ghcPath)- , hunit "BuildDeps/InternalLibrary0"- (PackageTests.BuildDeps.InternalLibrary0.Check.suite version ghcPath)- , hunit "PreProcess" (PackageTests.PreProcess.Check.suite ghcPath)- , hunit "TestStanza" (PackageTests.TestStanza.Check.suite ghcPath)- -- ^ The Test stanza test will eventually be required- -- only for higher versions.- , testGroup "TestSuiteExeV10" (PackageTests.TestSuiteExeV10.Check.checks ghcPath)- , hunit "TestOptions" (PackageTests.TestOptions.Check.suite ghcPath)- , hunit "BenchmarkStanza" (PackageTests.BenchmarkStanza.Check.suite ghcPath)- -- ^ The benchmark stanza test will eventually be required- -- only for higher versions.- , hunit "BenchmarkExeV10/Test"- (PackageTests.BenchmarkExeV10.Check.checkBenchmark ghcPath)- , hunit "BenchmarkOptions" (PackageTests.BenchmarkOptions.Check.suite ghcPath)- , hunit "TemplateHaskell/vanilla"- (PackageTests.TemplateHaskell.Check.vanilla ghcPath)- , hunit "TemplateHaskell/profiling"- (PackageTests.TemplateHaskell.Check.profiling ghcPath)- , hunit "PathsModule/Executable"- (PackageTests.PathsModule.Executable.Check.suite ghcPath)- , hunit "PathsModule/Library" (PackageTests.PathsModule.Library.Check.suite ghcPath)- , hunit "DeterministicAr"- (PackageTests.DeterministicAr.Check.suite ghcPath ghcPkgPath)- , hunit "EmptyLib/emptyLib"- (PackageTests.EmptyLib.Check.emptyLib ghcPath)- , hunit "Haddock" (PackageTests.Haddock.Check.suite ghcPath)- , hunit "BuildTestSuiteDetailedV09"- (PackageTests.BuildTestSuiteDetailedV09.Check.suite inplaceSpec ghcPath)- , hunit "OrderFlags"- (PackageTests.OrderFlags.Check.suite ghcPath)- , hunit "TemplateHaskell/dynamic"- (PackageTests.TemplateHaskell.Check.dynamic ghcPath)- , hunit "ReexportedModules"- (PackageTests.ReexportedModules.Check.suite ghcPath)- ] ++- -- These tests are only required to pass on cabal version >= 1.7- (if version >= Version [1, 7] []- then [ hunit "BuildDeps/TargetSpecificDeps1"- (PackageTests.BuildDeps.TargetSpecificDeps1.Check.suite ghcPath)- , hunit "BuildDeps/TargetSpecificDeps2"- (PackageTests.BuildDeps.TargetSpecificDeps2.Check.suite ghcPath)- , hunit "BuildDeps/TargetSpecificDeps3"- (PackageTests.BuildDeps.TargetSpecificDeps3.Check.suite ghcPath)- , hunit "BuildDeps/InternalLibrary1"- (PackageTests.BuildDeps.InternalLibrary1.Check.suite ghcPath)- , hunit "BuildDeps/InternalLibrary2"- (PackageTests.BuildDeps.InternalLibrary2.Check.suite ghcPath ghcPkgPath)- , hunit "BuildDeps/InternalLibrary3"- (PackageTests.BuildDeps.InternalLibrary3.Check.suite ghcPath ghcPkgPath)- , hunit "BuildDeps/InternalLibrary4"- (PackageTests.BuildDeps.InternalLibrary4.Check.suite ghcPath ghcPkgPath)- , hunit "PackageTests/CMain"- (PackageTests.CMain.Check.checkBuild ghcPath)- ]- else [])+#if MIN_VERSION_base(4,6,0)+import System.Environment ( getExecutablePath )+#endif main :: IO () main = do- -- WORKAROUND: disable buffering on stdout to get streaming test logs- -- test providers _should_ do this themselves- hSetBuffering stdout NoBuffering+ -- In abstract, the Cabal test suite makes calls to the "Setup"+ -- executable and tests the output of Cabal. However, we have to+ -- responsible for building this executable in the first place,+ -- since (1) Cabal doesn't support a test-suite depending on an+ -- executable, so we can't put a "Setup" executable in the Cabal+ -- file and then depend on it, (2) we don't want to call the Cabal+ -- functions *directly* because we need to capture and save the+ -- stdout and stderr, and (3) even if we could do all that, we will+ -- want to test some Custom setup scripts, which will be specific to+ -- the test at hand and need to be compiled against Cabal.+ --+ -- To be able to build the executable, there is some information+ -- we need:+ --+ -- 1. We need to know what ghc to use,+ --+ -- 2. We need to know what package databases (plural!) contain+ -- all of the necessary dependencies to make our Cabal package+ -- well-formed.+ --+ -- We could have the user pass these all in as arguments (TODO: this+ -- should be an option), but there's a more convenient way to get+ -- this information: the *build configuration* that was used to+ -- build the Cabal library (and this test suite) in the first place.+ -- To do this, we need to find the 'dist' directory that was set as+ -- the build directory for Cabal. - wd <- getCurrentDirectory- let dbFile = wd </> "dist/package.conf.inplace"- inplaceSpec = PackageSpec- { directory = []- , configOpts = [ "--package-db=" ++ dbFile- , "--constraint=Cabal == " ++ display cabalVersion- ]- , distPref = Nothing- }- putStrLn $ "Cabal test suite - testing cabal version " ++- display cabalVersion- lbi <- getPersistBuildConfig_ ("dist" </> "setup-config")- (ghc, _) <- requireProgram normal ghcProgram (withPrograms lbi)- (ghcPkg, _) <- requireProgram normal ghcPkgProgram (withPrograms lbi)- (haddock, _) <- requireProgram normal haddockProgram (withPrograms lbi)- let ghcPath = programPath ghc- ghcPkgPath = programPath ghcPkg- haddockPath = programPath haddock- putStrLn $ "Using ghc: " ++ ghcPath- putStrLn $ "Using ghc-pkg: " ++ ghcPkgPath- putStrLn $ "Using haddock: " ++ haddockPath- setCurrentDirectory "tests"+ dist_dir <- guessDistDir+ -- Might be bottom, if we can't figure it out. If you override+ -- all the relevant parameters you might still succeed.+ lbi <- getPersistBuildConfig_ (dist_dir </> "setup-config")++ -- You need to run the test suite in the right directory, sorry.+ test_dir <- getCurrentDirectory++ -- Pull out the information we need from the LBI+ -- TODO: The paths to GHC are configurable by command line, but you+ -- have to be careful: some tests might depend on the Cabal library,+ -- in which case you REALLY need to have built and installed Cabal+ -- for the version that the test suite is being built against. The+ -- easiest thing to do is make sure you built Cabal the same way as+ -- you will run the tests.+ let getExePathFromEnvOrLBI env_name prog = do+ r <- lookupEnv env_name+ case r of+ Nothing -> do+ (conf, _) <- requireProgram normal prog (withPrograms lbi)+ return (programPath conf)+ Just x -> return x+ -- It is too much damn work to actually properly configure it+ -- (Cabal will go off and probe GHC and we really aren't keen+ -- on doing this every time we run the test suite.)+ ghc_path <- getExePathFromEnvOrLBI "CABAL_PACKAGETESTS_GHC" ghcProgram+ ghc_pkg_path <- getExePathFromEnvOrLBI "CABAL_PACKAGETESTS_GHC_PKG"+ ghcPkgProgram+ haddock_path <- getExePathFromEnvOrLBI "CABAL_PACKAGETESTS_HADDOCK"+ haddockProgram++ with_ghc_path <- fromMaybe ghc_path+ `fmap` lookupEnv "CABAL_PACKAGETESTS_WITH_GHC"++ ghc_version_env <- lookupEnv "CABAL_PACKAGETESTS_GHC_VERSION"+ ghc_version <- case ghc_version_env of+ Nothing -> do+ (ghcConf, _) <- requireProgram normal ghcProgram (withPrograms lbi)+ return (fromJust (programVersion ghcConf))+ Just str ->+ return (fromJust (simpleParse str))++ with_ghc_version <- do+ version <- programFindVersion ghcProgram normal with_ghc_path+ case version of+ Nothing -> error "Cannot determine version of GHC used for --with-ghc"+ Just v -> return v++ -- Package DBs are not guaranteed to be absolute, so make them so in+ -- case a subprocess using the package DB needs a different CWD.+ db_stack_env <- lookupEnv "CABAL_PACKAGETESTS_DB_STACK"+ let packageDBStack0 = case db_stack_env of+ Nothing -> withPackageDB lbi+ Just str -> interpretPackageDbFlags True -- user install? why not.+ (concatMap readPackageDbList+ (splitSearchPath str))+ packageDBStack1 <- mapM canonicalizePackageDB packageDBStack0++ -- The packageDBStack is worth some commentary. The database+ -- stack we extract from the LBI will contain enough package+ -- databases to make the Cabal package well-formed. However,+ -- it does not *contain* the inplace installed Cabal package.+ -- So we need to add that to the stack.+ let packageDBStack2+ = packageDBStack1 +++ [SpecificPackageDB+ (dist_dir </> "package.conf.inplace")]++ -- THIS ISN'T EVEN MY FINAL FORM. The package database stack+ -- controls where we install a package; specifically, the package is+ -- installed to the top-most package on the stack (this makes the+ -- most sense, since it could depend on any of the packages below+ -- it.) If the test wants to register anything (as opposed to just+ -- working in place), then we need to have another temporary+ -- database we can install into (and not accidentally clobber any of+ -- the other stacks.) This is done on a per-test basis.+ --+ -- ONE MORE THING. On the subject of installing the package (with+ -- copy/register) it is EXTREMELY important that we also overload+ -- the install directories, so we don't clobber anything in the+ -- default install paths. VERY IMPORTANT.++ -- TODO: make this controllable by a flag+ verbosity <- maybe normal (readEOrFail flagToVerbosity)+ `fmap` lookupEnv "VERBOSE"+ -- The inplaceDB is where the Cabal library was registered+ -- in place (and is usable.) inplaceConfig is a convenient+ -- set of flags to make sure we make it visible.+ let suite = SuiteConfig+ { cabalDistPref = dist_dir+ , ghcPath = ghc_path+ , ghcVersion = ghc_version+ , ghcPkgPath = ghc_pkg_path+ , withGhcPath = with_ghc_path+ , withGhcVersion = with_ghc_version+ , packageDBStack = packageDBStack2+ , suiteVerbosity = verbosity+ , absoluteCWD = test_dir+ }++ putStrLn $ "Cabal test suite - testing cabal version "+ ++ display cabalVersion+ putStrLn $ "Cabal build directory: " ++ dist_dir+ putStrLn $ "Test directory: " ++ test_dir+ -- TODO: it might be useful to factor this out so that ./Setup+ -- configure dumps this file, so we can read it without in a version+ -- stable way.+ putStrLn $ "Environment:"+ putStrLn $ "CABAL_PACKAGETESTS_GHC=" ++ show ghc_path ++ " \\"+ putStrLn $ "CABAL_PACKAGETESTS_GHC_VERSION="+ ++ show (display ghc_version) ++ " \\"+ putStrLn $ "CABAL_PACKAGETESTS_GHC_PKG=" ++ show ghc_pkg_path ++ " \\"+ putStrLn $ "CABAL_PACKAGETESTS_WITH_GHC=" ++ show with_ghc_path ++ " \\"+ putStrLn $ "CABAL_PACKAGETESTS_HADDOCK=" ++ show haddock_path ++ " \\"+ -- For brevity, do pre-canonicalization+ putStrLn $ "CABAL_PACKAGETESTS_DB_STACK=" +++ show (intercalate [searchPathSeparator]+ (showPackageDbList (uninterpretPackageDBFlags+ packageDBStack0)))+ -- Create a shared Setup executable to speed up Simple tests- compileSetup "." ghcPath- defaultMain (tests cabalVersion inplaceSpec ghcPath ghcPkgPath)+ putStrLn $ "Building shared ./Setup executable"+ rawCompileSetup verbosity suite [] "tests" --- Like Distribution.Simple.Configure.getPersistBuildConfig but+ defaultMainWithIngredients options $+ runTestTree "Package Tests" (tests suite)++-- Reverse of 'interpretPackageDbFlags'.+-- prop_idem stk b+-- = interpretPackageDbFlags b (uninterpretPackageDBFlags stk) == stk+uninterpretPackageDBFlags :: PackageDBStack -> [Maybe PackageDB]+uninterpretPackageDBFlags stk = Nothing : map (\x -> Just x) stk++-- | Guess what the 'dist' directory Cabal was installed in is. There's+-- no 100% reliable way to find this, but there are a few good shots:+--+-- 1. Test programs are ~always built in-place, in a directory+-- that looks like dist/build/package-tests/package-tests;+-- thus the directory can be determined by looking at $0.+-- This method is robust against sandboxes, Nix local+-- builds, and Stack, but doesn't work if you're running+-- in an interpreter.+--+-- 2. We can use the normal input methods (as per Cabal),+-- checking for the CABAL_BUILDDIR environment variable as+-- well as the default location in the current working directory.+--+-- NB: If you update this, also update its copy in cabal-install's+-- IntegrationTests+guessDistDir :: IO FilePath+guessDistDir = do+#if MIN_VERSION_base(4,6,0)+ -- Method (1)+ -- TODO: this needs to be BC'ified, probably.+ exe_path <- canonicalizePath =<< getExecutablePath+ -- exe_path is something like /path/to/dist/build/package-tests/package-tests+ let dist0 = dropFileName exe_path </> ".." </> ".."+ b <- doesFileExist (dist0 </> "setup-config")+#else+ let dist0 = error "no path"+ b = False+#endif+ -- Method (2)+ if b then canonicalizePath dist0+ else findDistPrefOrDefault NoFlag >>= canonicalizePath++canonicalizePackageDB :: PackageDB -> IO PackageDB+canonicalizePackageDB (SpecificPackageDB path)+ = SpecificPackageDB `fmap` canonicalizePath path+canonicalizePackageDB x = return x++-- | Like Distribution.Simple.Configure.getPersistBuildConfig but -- doesn't check that the Cabal version matches, which it doesn't when -- we run Cabal's own test suite, due to bootstrapping issues.+-- Here's the situation:+--+-- 1. There's some system Cabal-1.0 installed. We use this+-- to build Setup.hs+-- 2. We run ./Setup configure, which uses Cabal-1.0 to+-- write out the LocalBuildInfo+-- 3. We build the Cabal library, whose version is Cabal-2.0+-- 4. We build the package-tests executable, which LINKS AGAINST+-- Cabal-2.0+-- 5. We try to read the LocalBuildInfo that ./Setup configure+-- wrote out, but it's Cabal-1.0 format!+--+-- It's a bit skeevy that we're trying to read Cabal-1.0 LocalBuildInfo+-- using Cabal-2.0's parser, but this seems to work OK in practice+-- because LocalBuildInfo is a slow-moving data structure. If+-- we ever make a major change, this won't work, and we'll have to+-- take a different approach (either setting "build-type: Custom"+-- so we bootstrap with the most recent Cabal, or by writing the+-- information we need in another format.) getPersistBuildConfig_ :: FilePath -> IO LocalBuildInfo getPersistBuildConfig_ filename = do eLBI <- try $ getConfigStateFile filename case eLBI of Left (ConfigStateFileBadVersion _ _ (Right lbi)) -> return lbi- Left (ConfigStateFileBadVersion _ _ (Left err)) -> throw err- Left err -> throw err+ -- These errors are lazy! We might not need these parameters.+ Left (ConfigStateFileBadVersion _ _ (Left err))+ -> return . error $+ "We couldn't understand the build configuration. Try " +++ "editing Cabal.cabal to have 'build-type: Custom' " +++ "and then rebuilding, or manually specifying CABAL_PACKAGETESTS_* " +++ "environment variables (see README.md for more details)." +++ "\n\nOriginal error: " +++ show err+ Left err -> return (throw err) Right lbi -> return lbi++options :: [Ingredient]+options = includingOptions+ [Option (Proxy :: Proxy OptionEnableAllTests)] :+ defaultIngredients
+ tests/PackageTests/AllowNewer/AllowNewer.cabal view
@@ -0,0 +1,25 @@+name: AllowNewer+version: 0.1.0.0+license: BSD3+author: Foo Bar+maintainer: cabal-dev@haskell.org+build-type: Simple+cabal-version: >=1.10++library+ exposed-modules: Foo+ hs-source-dirs: src+ build-depends: base < 1+ default-language: Haskell2010++test-suite foo-test+ type: exitcode-stdio-1.0+ main-is: Test.hs+ hs-source-dirs: tests+ build-depends: base < 1++benchmark foo-bench+ type: exitcode-stdio-1.0+ main-is: Bench.hs+ hs-source-dirs: benchmarks+ build-depends: base < 1
+ tests/PackageTests/AllowNewer/benchmarks/Bench.hs view
@@ -0,0 +1,4 @@+module Main where++main :: IO ()+main = return ()
+ tests/PackageTests/AllowNewer/src/Foo.hs view
@@ -0,0 +1,4 @@+module Main where++main :: IO ()+main = return ()
+ tests/PackageTests/AllowNewer/tests/Test.hs view
@@ -0,0 +1,4 @@+!module Main where++main :: IO ()+main = return ()
− tests/PackageTests/BenchmarkExeV10/Check.hs
@@ -1,16 +0,0 @@-module PackageTests.BenchmarkExeV10.Check- ( checkBenchmark- ) where--import PackageTests.PackageTester-import System.FilePath-import Test.HUnit--dir :: FilePath-dir = "PackageTests" </> "BenchmarkExeV10"--checkBenchmark :: FilePath -> Test-checkBenchmark ghcPath = TestCase $ do- let spec = PackageSpec dir Nothing ["--enable-benchmarks"]- buildResult <- cabal_build spec ghcPath- assertBuildSucceeded buildResult
− tests/PackageTests/BenchmarkOptions/Check.hs
@@ -1,26 +0,0 @@-module PackageTests.BenchmarkOptions.Check where--import PackageTests.PackageTester-import System.FilePath-import Test.HUnit--suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "BenchmarkOptions"- , configOpts = ["--enable-benchmarks"]- , distPref = Nothing- }- _ <- cabal_build spec ghcPath- result <- cabal_bench spec ["--benchmark-options=1 2 3"] ghcPath- let message = "\"cabal bench\" did not pass the correct options to the "- ++ "benchmark executable with \"--benchmark-options\""- assertEqual message True $ successful result- result' <- cabal_bench spec [ "--benchmark-option=1"- , "--benchmark-option=2"- , "--benchmark-option=3"- ]- ghcPath- let message' = "\"cabal bench\" did not pass the correct options to the "- ++ "benchmark executable with \"--benchmark-option\""- assertEqual message' True $ successful result'
tests/PackageTests/BenchmarkStanza/Check.hs view
@@ -1,52 +1,30 @@ module PackageTests.BenchmarkStanza.Check where -import Test.HUnit-import System.FilePath-import qualified Data.Map as Map import PackageTests.PackageTester+ import Distribution.Version-import Distribution.PackageDescription.Parse- ( readPackageDescription )-import Distribution.PackageDescription.Configuration- ( finalizePackageDescription )+import Distribution.Simple.LocalBuildInfo import Distribution.Package- ( PackageName(..), Dependency(..) ) import Distribution.PackageDescription- ( PackageDescription(..), BuildInfo(..), Benchmark(..)- , BenchmarkInterface(..)- , emptyBuildInfo- , emptyBenchmark, defaultRenaming )-import Distribution.Verbosity (silent)-import Distribution.System (buildPlatform)-import Distribution.Compiler- ( CompilerId(..), CompilerFlavor(..), unknownCompilerInfo, AbiTag(..) )-import Distribution.Text -suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let dir = "PackageTests" </> "BenchmarkStanza"- pdFile = dir </> "my" <.> "cabal"- spec = PackageSpec { directory = dir, configOpts = [], distPref = Nothing }- result <- cabal_configure spec ghcPath- assertOutputDoesNotContain "unknown section type" result- genPD <- readPackageDescription silent pdFile- let compiler = unknownCompilerInfo (CompilerId GHC $ Version [6, 12, 2] []) NoAbiTag- anticipatedBenchmark = emptyBenchmark+suite :: TestM ()+suite = do+ assertOutputDoesNotContain "unknown section type"+ =<< cabal' "configure" []+ dist_dir <- distDir+ lbi <- liftIO $ getPersistBuildConfig dist_dir+ let anticipatedBenchmark = emptyBenchmark { benchmarkName = "dummy"- , benchmarkInterface = BenchmarkExeV10 (Version [1,0] []) "dummy.hs"+ , benchmarkInterface = BenchmarkExeV10 (Version [1,0] [])+ "dummy.hs" , benchmarkBuildInfo = emptyBuildInfo { targetBuildDepends = [ Dependency (PackageName "base") anyVersion ]- , targetBuildRenaming =- Map.singleton (PackageName "base") defaultRenaming , hsSourceDirs = ["."] } , benchmarkEnabled = False }- case finalizePackageDescription [] (const True) buildPlatform compiler [] genPD of- Left xs -> let depMessage = "should not have missing dependencies:\n" ++- (unlines $ map (show . disp) xs)- in assertEqual depMessage True False- Right (f, _) -> let gotBenchmark = head $ benchmarks f- in assertEqual "parsed benchmark stanza does not match anticipated"- gotBenchmark anticipatedBenchmark+ gotBenchmark = head $ benchmarks (localPkgDescr lbi)+ assertEqual "parsed benchmark stanza does not match anticipated"+ anticipatedBenchmark gotBenchmark+ return ()
− tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive1/Check.hs
@@ -1,22 +0,0 @@-module PackageTests.BuildDeps.GlobalBuildDepsNotAdditive1.Check where--import Test.HUnit-import PackageTests.PackageTester-import System.FilePath-import Data.List-import Control.Exception-import Prelude hiding (catch)---suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec ("PackageTests" </> "BuildDeps" </> "GlobalBuildDepsNotAdditive1") []- result <- cabal_build spec ghcPath- do- assertEqual "cabal build should fail - see test-log.txt" False (successful result)- let sb = "Could not find module `Prelude'"- assertBool ("cabal output should be "++show sb) $- sb `isInfixOf` outputText result- `catch` \exc -> do- putStrLn $ "Cabal result was "++show result- throwIO (exc :: SomeException)
tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive1/GlobalBuildDepsNotAdditive1.cabal view
@@ -17,4 +17,4 @@ Library exposed-modules: MyLibrary- build-depends: bytestring, old-time+ build-depends: bytestring, pretty
tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive1/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc" C.putStrLn $ C.pack text
− tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive2/Check.hs
@@ -1,22 +0,0 @@-module PackageTests.BuildDeps.GlobalBuildDepsNotAdditive2.Check where--import Test.HUnit-import PackageTests.PackageTester-import System.FilePath-import Data.List-import Control.Exception-import Prelude hiding (catch)---suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec ("PackageTests" </> "BuildDeps" </> "GlobalBuildDepsNotAdditive2") []- result <- cabal_build spec ghcPath- do- assertEqual "cabal build should fail - see test-log.txt" False (successful result)- let sb = "Could not find module `Prelude'"- assertBool ("cabal output should be "++show sb) $- sb `isInfixOf` outputText result- `catch` \exc -> do- putStrLn $ "Cabal result was "++show result- throwIO (exc :: SomeException)
tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive2/GlobalBuildDepsNotAdditive2.cabal view
@@ -17,4 +17,4 @@ Executable lemon main-is: lemon.hs- build-depends: bytestring, old-time+ build-depends: bytestring, pretty
tests/PackageTests/BuildDeps/GlobalBuildDepsNotAdditive2/lemon.hs view
@@ -1,7 +1,7 @@ import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint main = do- getClockTime+ putStrLn (render (text "foo")) let text = "lemon" C.putStrLn $ C.pack text
− tests/PackageTests/BuildDeps/InternalLibrary0/Check.hs
@@ -1,22 +0,0 @@-module PackageTests.BuildDeps.InternalLibrary0.Check where--import Control.Monad-import Data.Version-import PackageTests.PackageTester-import System.FilePath-import Test.HUnit---suite :: Version -> FilePath -> Test-suite cabalVersion ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "BuildDeps" </> "InternalLibrary0"- , configOpts = []- , distPref = Nothing- }- result <- cabal_build spec ghcPath- assertBuildFailed result- when (cabalVersion >= Version [1, 7] []) $ do- let sb = "library which is defined within the same package."- -- In 1.7 it should tell you how to enable the desired behaviour.- assertOutputContains sb result
tests/PackageTests/BuildDeps/InternalLibrary0/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/InternalLibrary0/my.cabal view
@@ -16,9 +16,9 @@ Library exposed-modules: MyLibrary- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty Executable lemon main-is: lemon.hs hs-source-dirs: programs- build-depends: base, bytestring, old-time, InternalLibrary0+ build-depends: base, bytestring, pretty, InternalLibrary0
tests/PackageTests/BuildDeps/InternalLibrary0/programs/lemon.hs view
@@ -1,6 +1,6 @@-import System.Time+import Text.PrettyPrint import MyLibrary main = do- getClockTime+ putStrLn (render (text "foo")) myLibFunc
− tests/PackageTests/BuildDeps/InternalLibrary1/Check.hs
@@ -1,16 +0,0 @@-module PackageTests.BuildDeps.InternalLibrary1.Check where--import PackageTests.PackageTester-import System.FilePath-import Test.HUnit---suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "BuildDeps" </> "InternalLibrary1"- , configOpts = []- , distPref = Nothing- }- result <- cabal_build spec ghcPath- assertBuildSucceeded result
tests/PackageTests/BuildDeps/InternalLibrary1/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/InternalLibrary1/my.cabal view
@@ -15,9 +15,9 @@ Library exposed-modules: MyLibrary- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty Executable lemon main-is: lemon.hs hs-source-dirs: programs- build-depends: base, bytestring, old-time, InternalLibrary1+ build-depends: base, bytestring, pretty, InternalLibrary1
tests/PackageTests/BuildDeps/InternalLibrary1/programs/lemon.hs view
@@ -1,6 +1,6 @@-import System.Time+import Text.PrettyPrint import MyLibrary main = do- getClockTime+ putStrLn (render (text "foo")) myLibFunc
− tests/PackageTests/BuildDeps/InternalLibrary2/Check.hs
@@ -1,32 +0,0 @@-module PackageTests.BuildDeps.InternalLibrary2.Check where--import qualified Data.ByteString.Char8 as C-import PackageTests.PackageTester-import System.FilePath-import Test.HUnit---suite :: FilePath -> FilePath -> Test-suite ghcPath ghcPkgPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "BuildDeps" </> "InternalLibrary2"- , configOpts = []- , distPref = Nothing- }- let specTI = PackageSpec- { directory = directory spec </> "to-install"- , configOpts = []- , distPref = Nothing- }-- unregister "InternalLibrary2" ghcPkgPath- iResult <- cabal_install specTI ghcPath- assertInstallSucceeded iResult- bResult <- cabal_build spec ghcPath- assertBuildSucceeded bResult- unregister "InternalLibrary2" ghcPkgPath-- (_, _, output) <- run (Just $ directory spec) (directory spec </> "dist" </> "build" </> "lemon" </> "lemon") [] []- C.appendFile (directory spec </> "test-log.txt") (C.pack $ "\ndist/build/lemon/lemon\n"++output)- assertEqual "executable should have linked with the internal library" "myLibFunc internal" (concat $ lines output)-
tests/PackageTests/BuildDeps/InternalLibrary2/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc internal" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/InternalLibrary2/my.cabal view
@@ -15,9 +15,9 @@ Library exposed-modules: MyLibrary- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty Executable lemon main-is: lemon.hs hs-source-dirs: programs- build-depends: base, bytestring, old-time, InternalLibrary2+ build-depends: base, bytestring, pretty, InternalLibrary2
tests/PackageTests/BuildDeps/InternalLibrary2/programs/lemon.hs view
@@ -1,6 +1,6 @@-import System.Time+import Text.PrettyPrint import MyLibrary main = do- getClockTime+ putStrLn (render (text "foo")) myLibFunc
tests/PackageTests/BuildDeps/InternalLibrary2/to-install/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc installed" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/InternalLibrary2/to-install/my.cabal view
@@ -15,4 +15,4 @@ Library exposed-modules: MyLibrary- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty
− tests/PackageTests/BuildDeps/InternalLibrary3/Check.hs
@@ -1,32 +0,0 @@-module PackageTests.BuildDeps.InternalLibrary3.Check where--import qualified Data.ByteString.Char8 as C-import PackageTests.PackageTester-import System.FilePath-import Test.HUnit---suite :: FilePath -> FilePath -> Test-suite ghcPath ghcPkgPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "BuildDeps" </> "InternalLibrary3"- , configOpts = []- , distPref = Nothing- }- let specTI = PackageSpec- { directory = directory spec </> "to-install"- , configOpts = []- , distPref = Nothing- }-- unregister "InternalLibrary3" ghcPkgPath- iResult <- cabal_install specTI ghcPath- assertInstallSucceeded iResult- bResult <- cabal_build spec ghcPath- assertBuildSucceeded bResult- unregister "InternalLibrary3"ghcPkgPath-- (_, _, output) <- run (Just $ directory spec) (directory spec </> "dist" </> "build" </> "lemon" </> "lemon") [] []- C.appendFile (directory spec </> "test-log.txt") (C.pack $ "\ndist/build/lemon/lemon\n"++output)- assertEqual "executable should have linked with the internal library" "myLibFunc internal" (concat $ lines output)-
tests/PackageTests/BuildDeps/InternalLibrary3/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc internal" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/InternalLibrary3/my.cabal view
@@ -15,9 +15,9 @@ Library exposed-modules: MyLibrary- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty Executable lemon main-is: lemon.hs hs-source-dirs: programs- build-depends: base, bytestring, old-time, InternalLibrary3+ build-depends: base, bytestring, pretty, InternalLibrary3
tests/PackageTests/BuildDeps/InternalLibrary3/programs/lemon.hs view
@@ -1,6 +1,6 @@-import System.Time+import Text.PrettyPrint import MyLibrary main = do- getClockTime+ putStrLn (render (text "foo")) myLibFunc
tests/PackageTests/BuildDeps/InternalLibrary3/to-install/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc installed" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/InternalLibrary3/to-install/my.cabal view
@@ -15,4 +15,4 @@ Library exposed-modules: MyLibrary- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty
− tests/PackageTests/BuildDeps/InternalLibrary4/Check.hs
@@ -1,32 +0,0 @@-module PackageTests.BuildDeps.InternalLibrary4.Check where--import qualified Data.ByteString.Char8 as C-import PackageTests.PackageTester-import System.FilePath-import Test.HUnit---suite :: FilePath -> FilePath -> Test-suite ghcPath ghcPkgPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "BuildDeps" </> "InternalLibrary4"- , configOpts = []- , distPref = Nothing- }- let specTI = PackageSpec- { directory = directory spec </> "to-install"- , configOpts = []- , distPref = Nothing- }-- unregister "InternalLibrary4" ghcPkgPath- iResult <- cabal_install specTI ghcPath- assertInstallSucceeded iResult- bResult <- cabal_build spec ghcPath- assertBuildSucceeded bResult- unregister "InternalLibrary4" ghcPkgPath-- (_, _, output) <- run (Just $ directory spec) (directory spec </> "dist" </> "build" </> "lemon" </> "lemon") [] []- C.appendFile (directory spec </> "test-log.txt") (C.pack $ "\ndist/build/lemon/lemon\n"++output)- assertEqual "executable should have linked with the installed library" "myLibFunc installed" (concat $ lines output)-
tests/PackageTests/BuildDeps/InternalLibrary4/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc internal" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/InternalLibrary4/my.cabal view
@@ -15,9 +15,9 @@ Library exposed-modules: MyLibrary- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty Executable lemon main-is: lemon.hs hs-source-dirs: programs- build-depends: base, bytestring, old-time, InternalLibrary4 >= 0.2+ build-depends: base, bytestring, pretty, InternalLibrary4 >= 0.2
tests/PackageTests/BuildDeps/InternalLibrary4/programs/lemon.hs view
@@ -1,6 +1,6 @@-import System.Time+import Text.PrettyPrint import MyLibrary main = do- getClockTime+ putStrLn (render (text "foo")) myLibFunc
tests/PackageTests/BuildDeps/InternalLibrary4/to-install/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc installed" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/InternalLibrary4/to-install/my.cabal view
@@ -15,4 +15,4 @@ Library exposed-modules: MyLibrary- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty
− tests/PackageTests/BuildDeps/SameDepsAllRound/Check.hs
@@ -1,21 +0,0 @@-module PackageTests.BuildDeps.SameDepsAllRound.Check where--import Test.HUnit-import PackageTests.PackageTester-import System.FilePath-import qualified Control.Exception as E---suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "BuildDeps" </> "SameDepsAllRound"- , configOpts = []- , distPref = Nothing- }- result <- cabal_build spec ghcPath- do- assertEqual "cabal build should succeed - see test-log.txt" True (successful result)- `E.catch` \exc -> do- putStrLn $ "Cabal result was "++show result- E.throwIO (exc :: E.SomeException)
tests/PackageTests/BuildDeps/SameDepsAllRound/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/SameDepsAllRound/SameDepsAllRound.cabal view
@@ -25,7 +25,7 @@ Executable lemon main-is: lemon.hs- build-depends: old-time+ build-depends: pretty Executable pineapple main-is: pineapple.hs
tests/PackageTests/BuildDeps/SameDepsAllRound/lemon.hs view
@@ -1,7 +1,7 @@ import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint main = do- getClockTime+ putStrLn (render (text "foo")) let text = "lemon" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/SameDepsAllRound/pineapple.hs view
@@ -1,7 +1,7 @@ import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint main = do- getClockTime+ putStrLn (render (text "foo")) let text = "pineapple" C.putStrLn $ C.pack text
− tests/PackageTests/BuildDeps/TargetSpecificDeps1/Check.hs
@@ -1,29 +0,0 @@-module PackageTests.BuildDeps.TargetSpecificDeps1.Check where--import Test.HUnit-import PackageTests.PackageTester-import System.FilePath-import Data.List-import qualified Control.Exception as E-import Text.Regex.Posix---suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "BuildDeps" </> "TargetSpecificDeps1"- , configOpts = []- , distPref = Nothing- }- result <- cabal_build spec ghcPath- do- assertEqual "cabal build should fail - see test-log.txt" False (successful result)- assertBool "error should be in MyLibrary.hs" $- "MyLibrary.hs:" `isInfixOf` outputText result- assertBool "error should be \"Could not find module `System.Time\"" $- (intercalate " " $ lines $ outputText result)- =~ "Could not find module.*System.Time"-- `E.catch` \exc -> do- putStrLn $ "Cabal result was "++show result- E.throwIO (exc :: E.SomeException)
tests/PackageTests/BuildDeps/TargetSpecificDeps1/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/TargetSpecificDeps1/lemon.hs view
@@ -1,7 +1,7 @@ import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint main = do- getClockTime+ putStrLn (render (text "foo")) let text = "lemon" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/TargetSpecificDeps1/my.cabal view
@@ -19,4 +19,4 @@ Executable lemon main-is: lemon.hs- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty
− tests/PackageTests/BuildDeps/TargetSpecificDeps2/Check.hs
@@ -1,21 +0,0 @@-module PackageTests.BuildDeps.TargetSpecificDeps2.Check where--import Test.HUnit-import PackageTests.PackageTester-import System.FilePath-import qualified Control.Exception as E---suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "BuildDeps" </> "TargetSpecificDeps2"- , configOpts = []- , distPref = Nothing- }- result <- cabal_build spec ghcPath- do- assertEqual "cabal build should succeed - see test-log.txt" True (successful result)- `E.catch` \exc -> do- putStrLn $ "Cabal result was "++show result- E.throwIO (exc :: E.SomeException)
tests/PackageTests/BuildDeps/TargetSpecificDeps2/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/TargetSpecificDeps2/my.cabal view
@@ -17,7 +17,7 @@ Library exposed-modules: MyLibrary- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty Executable lemon main-is: lemon.hs
− tests/PackageTests/BuildDeps/TargetSpecificDeps3/Check.hs
@@ -1,28 +0,0 @@-module PackageTests.BuildDeps.TargetSpecificDeps3.Check where--import Test.HUnit-import PackageTests.PackageTester-import System.FilePath-import Data.List-import qualified Control.Exception as E-import Text.Regex.Posix---suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "BuildDeps" </> "TargetSpecificDeps3"- , configOpts = []- , distPref = Nothing- }- result <- cabal_build spec ghcPath- do- assertEqual "cabal build should fail - see test-log.txt" False (successful result)- assertBool "error should be in lemon.hs" $- "lemon.hs:" `isInfixOf` outputText result- assertBool "error should be \"Could not find module `System.Time\"" $- (intercalate " " $ lines $ outputText result)- =~ "Could not find module.*System.Time"- `E.catch` \exc -> do- putStrLn $ "Cabal result was "++show result- E.throwIO (exc :: E.SomeException)
tests/PackageTests/BuildDeps/TargetSpecificDeps3/MyLibrary.hs view
@@ -1,10 +1,10 @@ module MyLibrary where import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint myLibFunc :: IO () myLibFunc = do- getClockTime+ putStrLn (render (text "foo")) let text = "myLibFunc" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/TargetSpecificDeps3/lemon.hs view
@@ -1,7 +1,7 @@ import qualified Data.ByteString.Char8 as C-import System.Time+import Text.PrettyPrint main = do- getClockTime+ putStrLn (render (text "foo")) let text = "lemon" C.putStrLn $ C.pack text
tests/PackageTests/BuildDeps/TargetSpecificDeps3/my.cabal view
@@ -15,7 +15,7 @@ Library exposed-modules: MyLibrary- build-depends: base, bytestring, old-time+ build-depends: base, bytestring, pretty Executable lemon main-is: lemon.hs
− tests/PackageTests/BuildTestSuiteDetailedV09/Check.hs
@@ -1,18 +0,0 @@-module PackageTests.BuildTestSuiteDetailedV09.Check where--import Test.HUnit-import System.FilePath ((</>))--import PackageTests.PackageTester--suite :: PackageSpec -> FilePath -> Test-suite inplaceSpec ghcPath = TestCase $ do- let dir = "PackageTests" </> "BuildTestSuiteDetailedV09"- spec = inplaceSpec- { directory = dir- , configOpts = "--enable-tests" : configOpts inplaceSpec- }- confResult <- cabal_configure spec ghcPath- assertEqual "configure failed!" (successful confResult) True- buildResult <- cabal_build spec ghcPath- assertEqual "build failed!" (successful buildResult) True
− tests/PackageTests/BuildTestSuiteDetailedV09/Dummy.hs
@@ -1,6 +0,0 @@-module Dummy where--import Distribution.TestSuite (Test)--tests :: IO [Test]-tests = return []
+ tests/PackageTests/BuildTestSuiteDetailedV09/Dummy2.hs view
@@ -0,0 +1,6 @@+module Dummy2 where++import Distribution.TestSuite (Test)++tests :: IO [Test]+tests = return []
− tests/PackageTests/BuildTestSuiteDetailedV09/my.cabal
@@ -1,19 +0,0 @@-name: BuildTestSuiteDetailedV09-version: 0.1-license: BSD3-author: Thomas Tuegel-stability: stable-category: PackageTests-build-type: Simple--description:- Check that Cabal can build test suites of type detailed-0.9.--Library- exposed-modules: Dummy- build-depends: base, Cabal--test-suite test-Dummy- type: detailed-0.9- test-module: Dummy- build-depends: base, Cabal
+ tests/PackageTests/BuildableField/BuildableField.cabal view
@@ -0,0 +1,16 @@+name: BuildableField+version: 0.1.0.0+cabal-version: >=1.2+build-type: Simple+license: BSD3++flag build-exe+ default: True++library++executable my-executable+ build-depends: base, unavailable-package+ main-is: Main.hs+ if !flag(build-exe)+ buildable: False
+ tests/PackageTests/BuildableField/Main.hs view
@@ -0,0 +1,4 @@+import UnavailableModule++main :: IO ()+main = putStrLn "Hello"
− tests/PackageTests/CMain/Check.hs
@@ -1,20 +0,0 @@-module PackageTests.CMain.Check- ( checkBuild- ) where--import Test.HUnit-import System.FilePath-import PackageTests.PackageTester--dir :: FilePath-dir = "PackageTests" </> "CMain"--checkBuild :: FilePath -> Test-checkBuild ghcPath = TestCase $ do- let spec = PackageSpec- { directory = dir- , distPref = Nothing- , configOpts = []- }- buildResult <- cabal_build spec ghcPath- assertBuildSucceeded buildResult
− tests/PackageTests/CMain/Setup.hs
@@ -1,3 +0,0 @@-import Distribution.Simple-main = defaultMain-
tests/PackageTests/DeterministicAr/Check.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module PackageTests.DeterministicAr.Check where@@ -7,92 +7,36 @@ import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BS8 import Data.Char (isSpace)-import Data.List-#if __GLASGOW_HASKELL__ < 710-import Data.Traversable-#endif import PackageTests.PackageTester-import System.Exit-import System.FilePath import System.IO-import Test.HUnit (Assertion, Test (TestCase), assertFailure) import Distribution.Compiler (CompilerFlavor(..), CompilerId(..))-import Distribution.Package (packageKeyHash)+import Distribution.Package (getHSLibraryName) import Distribution.Version (Version(..)) import Distribution.Simple.Compiler (compilerId)-import Distribution.Simple.Configure (getPersistBuildConfig)-import Distribution.Simple.LocalBuildInfo (LocalBuildInfo, compiler, pkgKey)---- Perhaps these should live in PackageTester.---- For a polymorphic @IO a@ rather than @Assertion = IO ()@.-assertFailure' :: String -> IO a-assertFailure' msg = assertFailure msg >> return {-unpossible!-}undefined--ghcPkg_field :: String -> String -> FilePath -> IO [FilePath]-ghcPkg_field libraryName fieldName ghcPkgPath = do- (cmd, exitCode, raw) <- run Nothing ghcPkgPath []- ["--user", "field", libraryName, fieldName]- let output = filter ('\r' /=) raw -- Windows- -- copypasta of PackageTester.requireSuccess- unless (exitCode == ExitSuccess) . assertFailure $- "Command " ++ cmd ++ " failed.\n" ++ "output: " ++ output-- let prefix = fieldName ++ ": "- case traverse (stripPrefix prefix) (lines output) of- Nothing -> assertFailure' $ "Command " ++ cmd ++ " failed: expected "- ++ show prefix ++ " prefix on every line.\noutput: " ++ output- Just fields -> return fields--ghcPkg_field1 :: String -> String -> FilePath -> IO FilePath-ghcPkg_field1 libraryName fieldName ghcPkgPath = do- fields <- ghcPkg_field libraryName fieldName ghcPkgPath- case fields of- [field] -> return field- _ -> assertFailure' $ "Command ghc-pkg field failed: "- ++ "output not a single line.\noutput: " ++ show fields----------------------------------------------------------------------------this :: String-this = "DeterministicAr"--suite :: FilePath -> FilePath -> Test-suite ghcPath ghcPkgPath = TestCase $ do- let dir = "PackageTests" </> this- let spec = PackageSpec- { directory = dir- , configOpts = []- , distPref = Nothing- }-- unregister this ghcPkgPath- iResult <- cabal_install spec ghcPath- assertInstallSucceeded iResult+import Distribution.Simple.LocalBuildInfo (LocalBuildInfo, compiler, localUnitId) - let distBuild = dir </> "dist" </> "build"- libdir <- ghcPkg_field1 this "library-dirs" ghcPkgPath- lbi <- getPersistBuildConfig (dir </> "dist")- mapM_ (checkMetadata lbi) [distBuild, libdir]- unregister this ghcPkgPath+suite :: TestM ()+suite = do+ cabal_build []+ dist_dir <- distDir+ lbi <- liftIO $ getPersistBuildConfig dist_dir+ liftIO $ checkMetadata lbi (dist_dir </> "build") -- Almost a copypasta of Distribution.Simple.Program.Ar.wipeMetadata-checkMetadata :: LocalBuildInfo -> FilePath -> Assertion+checkMetadata :: LocalBuildInfo -> FilePath -> IO () checkMetadata lbi dir = withBinaryFile path ReadMode $ \ h -> do hFileSize h >>= checkArchive h where- path = dir </> "libHS" ++ this ++ "-0"- ++ (if ghc_7_10 then ("-" ++ packageKeyHash (pkgKey lbi)) else "")- ++ ".a"+ path = dir </> "lib" ++ getHSLibraryName (localUnitId lbi) ++ ".a" - ghc_7_10 = case compilerId (compiler lbi) of+ _ghc_7_10 = case compilerId (compiler lbi) of CompilerId GHC version | version >= Version [7, 10] [] -> True _ -> False - checkError msg = assertFailure' $+ checkError msg = assertFailure ( "PackageTests.DeterministicAr.checkMetadata: " ++ msg ++- " in " ++ path+ " in " ++ path) >> undefined archLF = "!<arch>\x0a" -- global magic, 8 bytes x60LF = "\x60\x0a" -- header magic, 2 bytes metadata = BS.concat
+ tests/PackageTests/DuplicateModuleName/DuplicateModuleName.cabal view
@@ -0,0 +1,25 @@+name: DuplicateModuleName+version: 0.1.0.0+license: BSD3+author: Edward Z. Yang+maintainer: ezyang@cs.stanford.edu+build-type: Simple+cabal-version: >=1.10++library+ exposed-modules: Foo+ hs-source-dirs: src+ build-depends: base, Cabal+ default-language: Haskell2010++test-suite foo+ type: detailed-0.9+ test-module: Foo+ hs-source-dirs: tests+ build-depends: base, Cabal, DuplicateModuleName++test-suite foo2+ type: detailed-0.9+ test-module: Foo+ hs-source-dirs: tests2+ build-depends: base, Cabal, DuplicateModuleName
+ tests/PackageTests/DuplicateModuleName/src/Foo.hs view
@@ -0,0 +1,12 @@+module Foo where++import Distribution.TestSuite++tests :: IO [Test]+tests = return [Test $ TestInstance+ { run = return (Finished (Fail "A"))+ , name = "test A"+ , tags = []+ , options = []+ , setOption = \_ _-> Left "No Options"+ }]
+ tests/PackageTests/DuplicateModuleName/tests/Foo.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE PackageImports #-}+module Foo where++import Distribution.TestSuite+import qualified "DuplicateModuleName" Foo as T++tests :: IO [Test]+tests = do+ r <- T.tests+ return $ [Test $ TestInstance+ { run = return (Finished (Fail "B"))+ , name = "test B"+ , tags = []+ , options = []+ , setOption = \_ _-> Left "No Options"+ }] ++ r++this_is_test = True
+ tests/PackageTests/DuplicateModuleName/tests2/Foo.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE PackageImports #-}+module Foo where++import Distribution.TestSuite+import qualified "DuplicateModuleName" Foo as T++tests :: IO [Test]+tests = do+ r <- T.tests+ return $ [Test $ TestInstance+ { run = return (Finished (Fail "C"))+ , name = "test C"+ , tags = []+ , options = []+ , setOption = \_ _-> Left "No Options"+ }] ++ r++this_is_test2 = True
− tests/PackageTests/EmptyLib/Check.hs
@@ -1,16 +0,0 @@-module PackageTests.EmptyLib.Check where--import PackageTests.PackageTester-import System.FilePath-import Test.HUnit---- See https://github.com/haskell/cabal/issues/1241-emptyLib :: FilePath -> Test-emptyLib ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "EmptyLib" </> "empty"- , configOpts = []- , distPref = Nothing- }- result <- cabal_build spec ghcPath- assertBuildSucceeded result
+ tests/PackageTests/GhcPkgGuess/SameDirectory/SameDirectory.cabal view
@@ -0,0 +1,11 @@+name: SameDirectory+version: 0.1.0.0+license: BSD3+author: Edward Z. Yang+maintainer: ezyang@cs.stanford.edu+build-type: Simple+cabal-version: >=1.10++library+ build-depends: base+ default-language: Haskell2010
+ tests/PackageTests/GhcPkgGuess/SameDirectory/ghc view
@@ -0,0 +1,6 @@+#!/bin/sh+if [ -z "$WITH_GHC" ]; then+ echo "Need to set WITH_GHC"+ exit 1+fi+exec "$WITH_GHC" "$@"
+ tests/PackageTests/GhcPkgGuess/SameDirectory/ghc-pkg view
@@ -0,0 +1,3 @@+#!/bin/sh+echo "GHC package manager version 9999999"+exit 0
+ tests/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/SameDirectory.cabal view
@@ -0,0 +1,11 @@+name: SameDirectory+version: 0.1.0.0+license: BSD3+author: Edward Z. Yang+maintainer: ezyang@cs.stanford.edu+build-type: Simple+cabal-version: >=1.10++library+ build-depends: base+ default-language: Haskell2010
+ tests/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/ghc-7.10 view
@@ -0,0 +1,6 @@+#!/bin/sh+if [ -z "$WITH_GHC" ]; then+ echo "Need to set WITH_GHC"+ exit 1+fi+exec "$WITH_GHC" "$@"
+ tests/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/ghc-pkg-ghc-7.10 view
@@ -0,0 +1,3 @@+#!/bin/sh+echo "GHC package manager version 9999999"+exit 0
+ tests/PackageTests/GhcPkgGuess/SameDirectoryVersion/SameDirectory.cabal view
@@ -0,0 +1,11 @@+name: SameDirectory+version: 0.1.0.0+license: BSD3+author: Edward Z. Yang+maintainer: ezyang@cs.stanford.edu+build-type: Simple+cabal-version: >=1.10++library+ build-depends: base+ default-language: Haskell2010
+ tests/PackageTests/GhcPkgGuess/SameDirectoryVersion/ghc-7.10 view
@@ -0,0 +1,6 @@+#!/bin/sh+if [ -z "$WITH_GHC" ]; then+ echo "Need to set WITH_GHC"+ exit 1+fi+exec "$WITH_GHC" "$@"
+ tests/PackageTests/GhcPkgGuess/SameDirectoryVersion/ghc-pkg-7.10 view
@@ -0,0 +1,3 @@+#!/bin/sh+echo "GHC package manager version 9999999"+exit 0
+ tests/PackageTests/GhcPkgGuess/Symlink/SameDirectory.cabal view
@@ -0,0 +1,11 @@+name: SameDirectory+version: 0.1.0.0+license: BSD3+author: Edward Z. Yang+maintainer: ezyang@cs.stanford.edu+build-type: Simple+cabal-version: >=1.10++library+ build-depends: base+ default-language: Haskell2010
+ tests/PackageTests/GhcPkgGuess/Symlink/bin/ghc view
@@ -0,0 +1,6 @@+#!/bin/sh+if [ -z "$WITH_GHC" ]; then+ echo "Need to set WITH_GHC"+ exit 1+fi+exec "$WITH_GHC" "$@"
+ tests/PackageTests/GhcPkgGuess/Symlink/bin/ghc-pkg view
@@ -0,0 +1,3 @@+#!/bin/sh+echo "GHC package manager version 9999999"+exit 0
+ tests/PackageTests/GhcPkgGuess/SymlinkGhcVersion/SameDirectory.cabal view
@@ -0,0 +1,11 @@+name: SameDirectory+version: 0.1.0.0+license: BSD3+author: Edward Z. Yang+maintainer: ezyang@cs.stanford.edu+build-type: Simple+cabal-version: >=1.10++library+ build-depends: base+ default-language: Haskell2010
+ tests/PackageTests/GhcPkgGuess/SymlinkGhcVersion/bin/ghc-7.10 view
@@ -0,0 +1,6 @@+#!/bin/sh+if [ -z "$WITH_GHC" ]; then+ echo "Need to set WITH_GHC"+ exit 1+fi+exec "$WITH_GHC" "$@"
+ tests/PackageTests/GhcPkgGuess/SymlinkGhcVersion/bin/ghc-pkg-7.10 view
@@ -0,0 +1,3 @@+#!/bin/sh+echo "GHC package manager version 9999999"+exit 0
+ tests/PackageTests/GhcPkgGuess/SymlinkVersion/SameDirectory.cabal view
@@ -0,0 +1,11 @@+name: SameDirectory+version: 0.1.0.0+license: BSD3+author: Edward Z. Yang+maintainer: ezyang@cs.stanford.edu+build-type: Simple+cabal-version: >=1.10++library+ build-depends: base+ default-language: Haskell2010
+ tests/PackageTests/GhcPkgGuess/SymlinkVersion/bin/ghc-7.10 view
@@ -0,0 +1,6 @@+#!/bin/sh+if [ -z "$WITH_GHC" ]; then+ echo "Need to set WITH_GHC"+ exit 1+fi+exec "$WITH_GHC" "$@"
+ tests/PackageTests/GhcPkgGuess/SymlinkVersion/bin/ghc-pkg-ghc-7.10 view
@@ -0,0 +1,3 @@+#!/bin/sh+echo "GHC package manager version 9999999"+exit 0
− tests/PackageTests/Haddock/Check.hs
@@ -1,42 +0,0 @@-module PackageTests.Haddock.Check (suite) where--import Control.Monad (unless, when)-import Data.List (isInfixOf)--import System.FilePath ((</>))-import System.Directory (doesDirectoryExist, removeDirectoryRecursive)-import Test.HUnit (Assertion, Test (TestCase), assertFailure)--import Distribution.Simple.Utils (withFileContents)-import PackageTests.PackageTester- (PackageSpec(..), assertHaddockSucceeded, cabal_haddock)--this :: String-this = "Haddock"--suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let dir = "PackageTests" </> this- haddocksDir = dir </> "dist" </> "doc" </> "html" </> "Haddock"- spec = PackageSpec- { directory = dir- , configOpts = []- , distPref = Nothing- }-- haddocksDirExists <- doesDirectoryExist haddocksDir- when haddocksDirExists (removeDirectoryRecursive haddocksDir)- hResult <- cabal_haddock spec [] ghcPath- assertHaddockSucceeded hResult-- let docFiles = map (haddocksDir </>)- ["CPP.html", "Literate.html", "NoCPP.html", "Simple.html"]- mapM_ (assertFindInFile "For hiding needles.") docFiles--assertFindInFile :: String -> FilePath -> Assertion-assertFindInFile needle path =- withFileContents path- (\contents ->- unless (needle `isInfixOf` contents)- (assertFailure ("expected: " ++ needle ++ "\n" ++- " in file: " ++ path)))
+ tests/PackageTests/HaddockNewline/A.hs view
@@ -0,0 +1,1 @@+module A where
+ tests/PackageTests/HaddockNewline/HaddockNewline.cabal view
@@ -0,0 +1,20 @@+name: HaddockNewline+version: 0.1.0.0+synopsis: This has a+ newline yo.+-- description: +license: BSD3+license-file: LICENSE+author: Edward Z. Yang+maintainer: ezyang@cs.stanford.edu+build-type: Simple+extra-source-files: ChangeLog.md+cabal-version: >=1.10++library+ exposed-modules: A+ -- other-modules: + -- other-extensions: + build-depends: base+ -- hs-source-dirs: + default-language: Haskell2010
+ tests/PackageTests/HaddockNewline/Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ tests/PackageTests/Options.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE DeriveDataTypeable #-}++module PackageTests.Options+ ( OptionEnableAllTests(..)+ ) where++import Data.Typeable (Typeable)++import Test.Tasty.Options (IsOption(..), flagCLParser, safeRead)++newtype OptionEnableAllTests = OptionEnableAllTests Bool+ deriving Typeable++instance IsOption OptionEnableAllTests where+ defaultValue = OptionEnableAllTests False+ parseValue = fmap OptionEnableAllTests . safeRead+ optionName = return "enable-all-tests"+ optionHelp = return "Enable all tests"+ optionCLParser = flagCLParser Nothing (OptionEnableAllTests True)
− tests/PackageTests/OrderFlags/Check.hs
@@ -1,24 +0,0 @@-module PackageTests.OrderFlags.Check where--import Test.HUnit-import PackageTests.PackageTester-import System.FilePath-import Control.Exception--#if !MIN_VERSION_base(4,6,0)-import Prelude hiding (catch)-#endif--suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "OrderFlags"- , configOpts = []- , distPref = Nothing- }- result <- cabal_build spec ghcPath- do- assertEqual "cabal build should succeed - see test-log.txt" True (successful result)- `catch` \exc -> do- putStrLn $ "Cabal result was "++show result- throwIO (exc :: SomeException)
tests/PackageTests/PackageTester.hs view
@@ -1,308 +1,693 @@ {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NondecreasingIndentation #-}+{-# LANGUAGE CPP #-} --- You can set the following VERBOSE environment variable to control--- the verbosity of the output generated by this module. module PackageTests.PackageTester- ( PackageSpec(..)- , Success(..)+ ( PackageSpec+ , SuiteConfig(..)+ , TestConfig(..) , Result(..)+ , TestM+ , runTestM + -- * Paths+ , packageDir+ , distDir+ , relativeDistDir+ , sharedDBPath+ , getWithGhcPath+ -- * Running cabal commands- , cabal_configure+ , cabal+ , cabal' , cabal_build- , cabal_haddock- , cabal_test- , cabal_bench , cabal_install- , unregister+ , ghcPkg+ , ghcPkg' , compileSetup , run+ , runExe+ , runExe'+ , rawRun+ , rawCompileSetup+ , withPackage+ , withEnv+ , withPackageDb + -- * Polymorphic versions of HUnit functions+ , assertFailure+ , assertEqual+ , assertBool+ , shouldExist+ , shouldNotExist+ -- * Test helpers- , assertBuildSucceeded- , assertBuildFailed- , assertHaddockSucceeded- , assertTestSucceeded- , assertInstallSucceeded+ , shouldFail+ , whenGhcVersion , assertOutputContains , assertOutputDoesNotContain+ , assertFindInFile+ , concatOutput+ , withSymlink++ -- * Test trees+ , TestTreeM+ , runTestTree+ , testTree+ , testTree'+ , groupTests+ , mapTestTrees+ , testWhen+ , testUnless+ , unlessWindows+ , hasSharedLibraries++ , getPersistBuildConfig++ -- Common utilities+ , module System.FilePath+ , module Data.List+ , module Control.Monad.IO.Class+ , module Text.Regex.Posix ) where -import qualified Control.Exception.Extensible as E+import PackageTests.Options++import Distribution.Compat.CreatePipe (createPipe)+import Distribution.Simple.Compiler (PackageDBStack, PackageDB(..))+import Distribution.Simple.Program.Run (getEffectiveEnvironment)+import Distribution.System (OS(Windows), buildOS)+import Distribution.Simple.Utils+ ( printRawCommandAndArgsAndEnv, withFileContents )+import Distribution.Simple.Configure+ ( getPersistBuildConfig )+import Distribution.Verbosity (Verbosity)+import Distribution.Simple.BuildPaths (exeExtension)++#ifndef CURRENT_COMPONENT_ID+import Distribution.Simple.Utils (cabalVersion)+import Distribution.Text (display)+#endif++import qualified Test.Tasty.HUnit as HUnit+import Text.Regex.Posix++import qualified Control.Exception as E import Control.Monad+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Writer+import Control.Monad.IO.Class import qualified Data.ByteString.Char8 as C import Data.List-import Data.Maybe-import System.Directory (canonicalizePath, doesFileExist, getCurrentDirectory)-import System.Environment (getEnv)-import System.Exit (ExitCode(ExitSuccess))+import Data.Version+import System.Directory+ ( doesFileExist, canonicalizePath, createDirectoryIfMissing+ , removeDirectoryRecursive, getPermissions, setPermissions+ , setOwnerExecutable )+import System.Exit import System.FilePath-import System.IO (hIsEOF, hGetChar, hClose)+import System.IO import System.IO.Error (isDoesNotExistError)-import System.Process (runProcess, waitForProcess)-import Test.HUnit (Assertion, assertFailure)+import System.Process (runProcess, waitForProcess, showCommandForUser)+import Test.Tasty (TestTree, askOption, testGroup) -import Distribution.Compat.CreatePipe (createPipe)-import Distribution.Simple.BuildPaths (exeExtension)-import Distribution.Simple.Program.Run (getEffectiveEnvironment)-import Distribution.Simple.Utils (printRawCommandAndArgsAndEnv)-import Distribution.ReadE (readEOrFail)-import Distribution.Verbosity (Verbosity, flagToVerbosity, normal)+#ifndef mingw32_HOST_OS+import Control.Monad.Catch ( bracket_ )+import System.Directory ( removeFile )+import System.Posix.Files ( createSymbolicLink )+#endif -data PackageSpec = PackageSpec- { directory :: FilePath- , distPref :: Maybe FilePath- , configOpts :: [String]- }+-- | Our test monad maintains an environment recording the global test+-- suite configuration 'SuiteConfig', and the local per-test+-- configuration 'TestConfig'.+type TestM = ReaderT (SuiteConfig, TestConfig) IO -data Success = Failure- | ConfigureSuccess- | BuildSuccess- | HaddockSuccess- | InstallSuccess- | TestSuccess- | BenchSuccess- deriving (Eq, Show)+-- | Run a test in the test monad.+runTestM :: SuiteConfig -> FilePath -> Maybe String -> TestM a -> IO ()+runTestM suite name subname m = do+ let test = TestConfig {+ testMainName = name,+ testSubName = subname,+ testShouldFail = False,+ testCurrentPackage = ".",+ testPackageDb = False,+ testEnvironment = []+ }+ void (runReaderT (cleanup >> m) (suite, test))+ where+ -- TODO: option not to clean up dist dirs; this should be+ -- harmless!+ cleanup = do+ onlyIfExists . removeDirectoryRecursive =<< topDir -data Result = Result- { successful :: Bool- , success :: Success- , outputText :: String- } deriving Show+-- | Run an IO action, and suppress a "does not exist" error.+onlyIfExists :: MonadIO m => IO () -> m ()+onlyIfExists m = liftIO $+ E.catch m $ \(e :: IOError) ->+ if isDoesNotExistError e+ then return ()+ else E.throwIO e -nullResult :: Result-nullResult = Result True Failure ""+-- cleaning up:+-- cabal clean will clean up dist directory, but we also need to zap+-- Setup etc.+--+-- Suggestion: just copy the files somewhere else! +-- | Global configuration for the entire test suite.+data SuiteConfig = SuiteConfig+ -- | Path to GHC that was used to compile Cabal library under test.+ { ghcPath :: FilePath+ -- | Version of GHC that compiled Cabal.+ , ghcVersion :: Version+ -- | Path to ghc-pkg corresponding to 'ghcPath'.+ , ghcPkgPath :: FilePath+ -- | Path to GHC that we should use to "./Setup --with-ghc"+ , withGhcPath :: FilePath+ -- | Version of GHC at 'withGhcPath'.+ , withGhcVersion :: Version+ -- | The build directory that was used to build Cabal (used+ -- to compile Setup scripts.)+ , cabalDistPref :: FilePath+ -- | Configuration options you can use to make the Cabal+ -- being tested visible (e.g. if you're using the test runner).+ -- We don't add these by default because then you have to+ -- link against Cabal which makes the build go longer.+ , packageDBStack :: PackageDBStack+ -- | How verbose should we be+ , suiteVerbosity :: Verbosity+ -- | The absolute current working directory+ , absoluteCWD :: FilePath+ }++data TestConfig = TestConfig+ -- | Test name, MUST be the directory the test packages live in+ -- relative to tests/PackageTests+ { testMainName :: FilePath+ -- | Test sub-name, used to qualify dist/database directory to avoid+ -- conflicts.+ , testSubName :: Maybe String+ -- | This gets modified sometimes+ , testShouldFail :: Bool+ -- | The "current" package, ala current directory+ , testCurrentPackage :: PackageSpec+ -- | Says if we've initialized the per-test package DB+ , testPackageDb :: Bool+ -- | Environment override+ , testEnvironment :: [(String, Maybe String)]+ }++-- | A package that can be built.+type PackageSpec = FilePath+ --------------------------------------------------------------------------- * Running cabal commands+-- * Directories -recordRun :: (String, ExitCode, String) -> Success -> Result -> Result-recordRun (cmd, exitCode, exeOutput) thisSucc res =- res { successful = successful res && exitCode == ExitSuccess- , success = if exitCode == ExitSuccess then thisSucc- else success res- , outputText =- (if null $ outputText res then "" else outputText res ++ "\n") ++- cmd ++ "\n" ++ exeOutput- }+simpleSetupPath :: TestM FilePath+simpleSetupPath = do+ (suite, _) <- ask+ return (absoluteCWD suite </> "tests/Setup") -cabal_configure :: PackageSpec -> FilePath -> IO Result-cabal_configure spec ghcPath = do- res <- doCabalConfigure spec ghcPath- record spec res- return res+-- | The absolute path to the directory containing the files for+-- this tests; usually @Check.hs@ and any test packages.+testDir :: TestM FilePath+testDir = do+ (suite, test) <- ask+ return $ absoluteCWD suite </> "tests/PackageTests" </> testMainName test -doCabalConfigure :: PackageSpec -> FilePath -> IO Result-doCabalConfigure spec ghcPath = do- cleanResult@(_, _, _) <- cabal spec [] ["clean"] ghcPath- requireSuccess cleanResult- res <- cabal spec []- (["configure", "--user", "-w", ghcPath] ++ configOpts spec)- ghcPath- return $ recordRun res ConfigureSuccess nullResult+-- | The absolute path to the root of the package directory; it's+-- where the Cabal file lives. This is what you want the CWD of cabal+-- calls to be.+packageDir :: TestM FilePath+packageDir = do+ (_, test) <- ask+ test_dir <- testDir+ return $ test_dir </> testCurrentPackage test -doCabalBuild :: PackageSpec -> FilePath -> IO Result-doCabalBuild spec ghcPath = do- configResult <- doCabalConfigure spec ghcPath- if successful configResult- then do- res <- cabal spec [] ["build", "-v"] ghcPath- return $ recordRun res BuildSuccess configResult- else- return configResult+-- | The absolute path to the directory containing all the+-- files for ALL tests associated with a test (respecting+-- subtests.) To clean, you ONLY need to delete this directory.+topDir :: TestM FilePath+topDir = do+ test_dir <- testDir+ (_, test) <- ask+ return $ test_dir </>+ case testSubName test of+ Nothing -> "dist-test"+ Just n -> "dist-test." ++ n -cabal_build :: PackageSpec -> FilePath -> IO Result-cabal_build spec ghcPath = do- res <- doCabalBuild spec ghcPath- record spec res- return res+prefixDir :: TestM FilePath+prefixDir = do+ top_dir <- topDir+ return $ top_dir </> "usr" -cabal_haddock :: PackageSpec -> [String] -> FilePath -> IO Result-cabal_haddock spec extraArgs ghcPath = do- res <- doCabalHaddock spec extraArgs ghcPath- record spec res- return res+-- | The absolute path to the build directory that should be used+-- for the current package in a test.+distDir :: TestM FilePath+distDir = do+ top_dir <- topDir+ (_, test) <- ask+ return $ top_dir </> testCurrentPackage test </> "dist" -doCabalHaddock :: PackageSpec -> [String] -> FilePath -> IO Result-doCabalHaddock spec extraArgs ghcPath = do- configResult <- doCabalConfigure spec ghcPath- if successful configResult- then do- res <- cabal spec [] ("haddock" : extraArgs) ghcPath- return $ recordRun res HaddockSuccess configResult- else- return configResult+definitelyMakeRelative :: FilePath -> FilePath -> FilePath+definitelyMakeRelative base0 path0 =+ let go [] path = joinPath path+ go base [] = joinPath (replicate (length base) "..")+ go (".":xs) ys = go xs ys+ go xs (".":ys) = go xs ys+ go (x:xs) (y:ys)+ | x == y = go xs ys+ | otherwise = go (x:xs) [] </> go [] (y:ys)+ in go (splitPath base0) (splitPath path0) -unregister :: String -> FilePath -> IO ()-unregister libraryName ghcPkgPath = do- res@(_, _, output) <- run Nothing ghcPkgPath [] ["unregister", "--user", libraryName]- if "cannot find package" `isInfixOf` output- then return ()- else requireSuccess res+-- hpc is stupid and doesn't understand absolute paths.+relativeDistDir :: TestM FilePath+relativeDistDir = do+ dist_dir0 <- distDir+ pkg_dir <- packageDir+ return $ definitelyMakeRelative pkg_dir dist_dir0 --- | Install this library in the user area-cabal_install :: PackageSpec -> FilePath -> IO Result-cabal_install spec ghcPath = do- buildResult <- doCabalBuild spec ghcPath- res <- if successful buildResult- then do- res <- cabal spec [] ["install"] ghcPath- return $ recordRun res InstallSuccess buildResult- else- return buildResult- record spec res- return res+-- | The absolute path to the shared package database that should+-- be used by all packages in this test.+sharedDBPath :: TestM FilePath+sharedDBPath = do+ top_dir <- topDir+ return $ top_dir </> "packagedb" -cabal_test :: PackageSpec -> [(String, Maybe String)] -> [String] -> FilePath -> IO Result-cabal_test spec envOverrides extraArgs ghcPath = do- res <- cabal spec envOverrides ("test" : extraArgs) ghcPath- let r = recordRun res TestSuccess nullResult- record spec r- return r+getWithGhcPath :: TestM FilePath+getWithGhcPath = do+ (suite, _) <- ask+ return $ withGhcPath suite -cabal_bench :: PackageSpec -> [String] -> FilePath -> IO Result-cabal_bench spec extraArgs ghcPath = do- res <- cabal spec [] ("bench" : extraArgs) ghcPath- let r = recordRun res BenchSuccess nullResult- record spec r- return r+------------------------------------------------------------------------+-- * Running cabal -compileSetup :: FilePath -> FilePath -> IO ()-compileSetup packageDir ghcPath = do- wd <- getCurrentDirectory- r <- run (Just $ packageDir) ghcPath []- [ "--make"--- HPC causes trouble -- see #1012--- , "-fhpc"- , "-package-conf " ++ wd </> "../dist/package.conf.inplace"- , "Setup.hs"- ]- requireSuccess r+cabal :: String -> [String] -> TestM ()+cabal cmd extraArgs0 = void (cabal' cmd extraArgs0) --- | Returns the command that was issued, the return code, and the output text.-cabal :: PackageSpec -> [(String, Maybe String)] -> [String] -> FilePath -> IO (String, ExitCode, String)-cabal spec envOverrides cabalArgs_ ghcPath = do- let cabalArgs = case distPref spec of- Nothing -> cabalArgs_- Just dist -> ("--builddir=" ++ dist) : cabalArgs_- customSetup <- doesFileExist (directory spec </> "Setup.hs")+cabal' :: String -> [String] -> TestM Result+cabal' cmd extraArgs0 = do+ (suite, test) <- ask+ prefix_dir <- prefixDir+ when ((cmd == "register" || cmd == "copy") && not (testPackageDb test)) $+ error "Cannot register/copy without using 'withPackageDb'"+ let extraArgs1 = case cmd of+ "configure" ->+ -- If the package database is empty, setting --global+ -- here will make us error loudly if we try to install+ -- into a bad place.+ [ "--global"+ , "--with-ghc", withGhcPath suite+ -- This improves precision but it increases the number+ -- of flags one has to specify and I don't like that;+ -- Cabal is going to configure it and usually figure+ -- out the right location in any case.+ -- , "--with-ghc-pkg", withGhcPkgPath suite+ -- Would really like to do this, but we're not always+ -- going to be building against sufficiently recent+ -- Cabal which provides this macro.+ -- , "--dependency=Cabal=" ++ THIS_PACKAGE_KEY+ -- These flags make the test suite run faster+ -- Can't do this unless we LD_LIBRARY_PATH correctly+ -- , "--enable-executable-dynamic"+ , "--disable-optimization"+ -- Specify where we want our installed packages to go+ , "--prefix=" ++ prefix_dir+ ] -- Only add the LBI package stack if the GHC version+ -- matches.+ ++ (if withGhcPath suite == ghcPath suite+ then packageDBParams (packageDBStack suite)+ else [])+ ++ extraArgs0+ -- This gives us MUCH better error messages+ "build" -> "-v" : extraArgs0+ _ -> extraArgs0+ -- This is a horrible hack to make hpc work correctly+ dist_dir <- relativeDistDir+ let extraArgs = ["--distdir", dist_dir] ++ extraArgs1+ doCabal (cmd:extraArgs)++-- | This abstracts the common pattern of configuring and then building.+cabal_build :: [String] -> TestM ()+cabal_build args = do+ cabal "configure" args+ cabal "build" []+ return ()++-- | This abstracts the common pattern of "installing" a package.+cabal_install :: [String] -> TestM ()+cabal_install args = do+ cabal "configure" args+ cabal "build" []+ cabal "copy" []+ cabal "register" []+ return ()++-- | Determines what Setup executable to run and runs it+doCabal :: [String] -- ^ extra arguments+ -> TestM Result+doCabal cabalArgs = do+ pkg_dir <- packageDir+ customSetup <- liftIO $ doesFileExist (pkg_dir </> "Setup.hs") if customSetup then do- compileSetup (directory spec) ghcPath- path <- canonicalizePath $ directory spec </> "Setup"- run (Just $ directory spec) path envOverrides cabalArgs+ compileSetup+ -- TODO make this less racey+ let path = pkg_dir </> "Setup"+ run (Just pkg_dir) path cabalArgs else do -- Use shared Setup executable (only for Simple build types).- path <- canonicalizePath "Setup"- run (Just $ directory spec) path envOverrides cabalArgs+ path <- simpleSetupPath+ run (Just pkg_dir) path cabalArgs --- | Returns the command that was issued, the return code, and the output text-run :: Maybe FilePath -> String -> [(String, Maybe String)] -> [String] -> IO (String, ExitCode, String)-run cwd path envOverrides args = do+packageDBParams :: PackageDBStack -> [String]+packageDBParams dbs = "--package-db=clear"+ : map (("--package-db=" ++) . convert) dbs+ where+ convert :: PackageDB -> String+ convert GlobalPackageDB = "global"+ convert UserPackageDB = "user"+ convert (SpecificPackageDB path) = path++------------------------------------------------------------------------+-- * Compiling setup scripts++compileSetup :: TestM ()+compileSetup = do+ (suite, test) <- ask+ pkg_path <- packageDir+ liftIO $ rawCompileSetup (suiteVerbosity suite) suite (testEnvironment test) pkg_path++rawCompileSetup :: Verbosity -> SuiteConfig -> [(String, Maybe String)] -> FilePath -> IO ()+rawCompileSetup verbosity suite e path = do+ -- NB: Use 'ghcPath', not 'withGhcPath', since we need to be able to+ -- link against the Cabal library which was built with 'ghcPath'.+ r <- rawRun verbosity (Just path) (ghcPath suite) e $+ [ "--make"] +++ ghcPackageDBParams (ghcVersion suite) (packageDBStack suite) +++ [ "-hide-all-packages"+ , "-package base"+#ifdef CURRENT_COMPONENT_ID+ -- This is best, but we don't necessarily have it+ -- if we're bootstrapping with old Cabal.+ , "-package-id " ++ CURRENT_COMPONENT_ID+#else+ -- This mostly works, UNLESS you've installed a+ -- version of Cabal with the SAME version number.+ -- Then old GHCs will incorrectly select the installed+ -- version (because it prefers the FIRST package it finds.)+ -- It also semi-works to not specify "-hide-all-packages"+ -- at all, except if there's a later version of Cabal+ -- installed GHC will prefer that.+ , "-package Cabal-" ++ display cabalVersion+#endif+ , "-O0"+ , "Setup.hs" ]+ unless (resultExitCode r == ExitSuccess) $+ error $+ "could not build shared Setup executable\n" +++ " ran: " ++ resultCommand r ++ "\n" +++ " output:\n" ++ resultOutput r ++ "\n\n"++ghcPackageDBParams :: Version -> PackageDBStack -> [String]+ghcPackageDBParams ghc_version dbs+ | ghc_version >= Version [7,6] []+ = "-clear-package-db" : map convert dbs+ | otherwise+ = concatMap convertLegacy dbs+ where+ convert :: PackageDB -> String+ convert GlobalPackageDB = "-global-package-db"+ convert UserPackageDB = "-user-package-db"+ convert (SpecificPackageDB path) = "-package-db=" ++ path++ convertLegacy :: PackageDB -> [String]+ convertLegacy (SpecificPackageDB path) = ["-package-conf=" ++ path]+ convertLegacy _ = []++------------------------------------------------------------------------+-- * Running ghc-pkg++ghcPkg :: String -> [String] -> TestM ()+ghcPkg cmd args = void (ghcPkg' cmd args)++ghcPkg' :: String -> [String] -> TestM Result+ghcPkg' cmd args = do+ db_path <- sharedDBPath+ (config, test) <- ask+ unless (testPackageDb test) $+ error "Must initialize package database using withPackageDb"+ let db_stack = packageDBStack config ++ [SpecificPackageDB db_path]+ extraArgs = ghcPkgPackageDBParams (ghcVersion config) db_stack+ run Nothing (ghcPkgPath config) (cmd : extraArgs ++ args)++ghcPkgPackageDBParams :: Version -> PackageDBStack -> [String]+ghcPkgPackageDBParams version dbs = concatMap convert dbs where+ convert :: PackageDB -> [String]+ -- Ignoring global/user is dodgy but there's no way good+ -- way to give ghc-pkg the correct flags in this case.+ convert GlobalPackageDB = []+ convert UserPackageDB = []+ convert (SpecificPackageDB path)+ | version >= Version [7,6] []+ = ["--package-db=" ++ path]+ | otherwise+ = ["--package-conf=" ++ path]++------------------------------------------------------------------------+-- * Running other things++-- | Run an executable that was produced by cabal. The @exe_name@+-- is precisely the name of the executable section in the file.+runExe :: String -> [String] -> TestM ()+runExe exe_name args = void (runExe' exe_name args)++runExe' :: String -> [String] -> TestM Result+runExe' exe_name args = do+ dist_dir <- distDir+ let exe = dist_dir </> "build" </> exe_name </> exe_name+ run Nothing exe args++run :: Maybe FilePath -> String -> [String] -> TestM Result+run mb_cwd path args = do verbosity <- getVerbosity+ (_, test) <- ask+ r <- liftIO $ rawRun verbosity mb_cwd path (testEnvironment test) args+ record r+ requireSuccess r++rawRun :: Verbosity -> Maybe FilePath -> String -> [(String, Maybe String)] -> [String] -> IO Result+rawRun verbosity mb_cwd path envOverrides args = do -- path is relative to the current directory; canonicalizePath makes it -- absolute, so that runProcess will find it even when changing directory. path' <- do pathExists <- doesFileExist path- canonicalizePath (if pathExists then path else path <.> exeExtension)+ canonicalizePath (if pathExists then path+ else path <.> exeExtension) menv <- getEffectiveEnvironment envOverrides printRawCommandAndArgsAndEnv verbosity path' args menv (readh, writeh) <- createPipe- pid <- runProcess path' args cwd menv Nothing (Just writeh) (Just writeh)+ pid <- runProcess path' args mb_cwd menv Nothing (Just writeh) (Just writeh) - -- fork off a thread to start consuming the output- out <- suckH [] readh+ out <- hGetContents readh+ void $ E.evaluate (length out) -- force the output hClose readh -- wait for the program to terminate exitcode <- waitForProcess pid- let fullCmd = unwords (path' : args)- return ("\"" ++ fullCmd ++ "\" in " ++ fromMaybe "" cwd, exitcode, out)- where- suckH output h = do- eof <- hIsEOF h- if eof- then return (reverse output)- else do- c <- hGetChar h- suckH (c:output) h+ return Result {+ resultExitCode = exitcode,+ resultDirectory = mb_cwd,+ resultCommand = showCommandForUser path' args,+ resultOutput = out+ } +------------------------------------------------------------------------+-- * Subprocess run results -requireSuccess :: (String, ExitCode, String) -> IO ()-requireSuccess (cmd, exitCode, output) =- unless (exitCode == ExitSuccess) $+data Result = Result+ { resultExitCode :: ExitCode+ , resultDirectory :: Maybe FilePath+ , resultCommand :: String+ , resultOutput :: String+ } deriving Show++requireSuccess :: Result -> TestM Result+requireSuccess r@Result { resultCommand = cmd+ , resultExitCode = exitCode+ , resultOutput = output } = do+ (_, test) <- ask+ when (exitCode /= ExitSuccess && not (testShouldFail test)) $ assertFailure $ "Command " ++ cmd ++ " failed.\n" ++- "output: " ++ output+ "Output:\n" ++ output ++ "\n"+ when (exitCode == ExitSuccess && testShouldFail test) $+ assertFailure $ "Command " ++ cmd ++ " succeeded.\n" +++ "Output:\n" ++ output ++ "\n"+ return r -record :: PackageSpec -> Result -> IO ()-record spec res = do- C.writeFile (directory spec </> "test-log.txt") (C.pack $ outputText res)+record :: Result -> TestM ()+record res = do+ build_dir <- distDir+ (suite, _) <- ask+ liftIO $ createDirectoryIfMissing True build_dir+ liftIO $ C.appendFile (build_dir </> "test.log")+ (C.pack $ "+ " ++ resultCommand res ++ "\n"+ ++ resultOutput res ++ "\n\n")+ let test_sh = build_dir </> "test.sh"+ b <- liftIO $ doesFileExist test_sh+ when (not b) . liftIO $ do+ -- This is hella racey but this is not that security important+ C.appendFile test_sh+ (C.pack $ "#/bin/sh\nset -ev\n" +++ "cd "++ show (absoluteCWD suite) ++"\n")+ perms <- getPermissions test_sh+ setPermissions test_sh (setOwnerExecutable True perms) + liftIO $ C.appendFile test_sh+ (C.pack+ (case resultDirectory res of+ Nothing -> resultCommand res+ Just d -> "(cd " ++ show d ++ " && " ++ resultCommand res ++ ")\n"))+ ------------------------------------------------------------------------ -- * Test helpers -assertBuildSucceeded :: Result -> Assertion-assertBuildSucceeded result = unless (successful result) $- assertFailure $- "expected: \'setup build\' should succeed\n" ++- " output: " ++ outputText result+assertFailure :: MonadIO m => String -> m ()+assertFailure = liftIO . HUnit.assertFailure -assertBuildFailed :: Result -> Assertion-assertBuildFailed result = when (successful result) $- assertFailure $- "expected: \'setup build\' should fail\n" ++- " output: " ++ outputText result+assertEqual :: (Eq a, Show a, MonadIO m) => String -> a -> a -> m ()+assertEqual s x y = liftIO $ HUnit.assertEqual s x y -assertHaddockSucceeded :: Result -> Assertion-assertHaddockSucceeded result = unless (successful result) $- assertFailure $- "expected: \'setup haddock\' should succeed\n" ++- " output: " ++ outputText result+assertBool :: MonadIO m => String -> Bool -> m ()+assertBool s x = liftIO $ HUnit.assertBool s x -assertTestSucceeded :: Result -> Assertion-assertTestSucceeded result = unless (successful result) $- assertFailure $- "expected: \'setup test\' should succeed\n" ++- " output: " ++ outputText result+shouldExist :: MonadIO m => FilePath -> m ()+shouldExist path = liftIO $ doesFileExist path >>= assertBool (path ++ " should exist") -assertInstallSucceeded :: Result -> Assertion-assertInstallSucceeded result = unless (successful result) $- assertFailure $- "expected: \'setup install\' should succeed\n" ++- " output: " ++ outputText result+shouldNotExist :: MonadIO m => FilePath -> m ()+shouldNotExist path =+ liftIO $ doesFileExist path >>= assertBool (path ++ " should exist") . not -assertOutputContains :: String -> Result -> Assertion+shouldFail :: TestM a -> TestM a+shouldFail = withReaderT (\(suite, test) -> (suite, test { testShouldFail = not (testShouldFail test) }))++whenGhcVersion :: (Version -> Bool) -> TestM () -> TestM ()+whenGhcVersion p m = do+ (suite, _) <- ask+ when (p (ghcVersion suite)) m++withPackage :: FilePath -> TestM a -> TestM a+withPackage f = withReaderT (\(suite, test) -> (suite, test { testCurrentPackage = f }))++-- TODO: Really should accumulate... but I think to do this+-- properly we can't just append+withEnv :: [(String, Maybe String)] -> TestM a -> TestM a+withEnv e m = do+ (_, test0) <- ask+ when (not (null (testEnvironment test0)))+ $ error "nested withEnv (not yet) supported"+ withReaderT (\(suite, test) -> (suite, test { testEnvironment = e })) m++withPackageDb :: TestM a -> TestM a+withPackageDb m = do+ (_, test0) <- ask+ db_path <- sharedDBPath+ if testPackageDb test0+ then m+ else withReaderT (\(suite, test) ->+ (suite { packageDBStack+ = packageDBStack suite+ ++ [SpecificPackageDB db_path] },+ test { testPackageDb = True }))+ $ do ghcPkg "init" [db_path]+ m++assertOutputContains :: MonadIO m => String -> Result -> m () assertOutputContains needle result = unless (needle `isInfixOf` (concatOutput output)) $ assertFailure $ " expected: " ++ needle ++ "\n" ++ " in output: " ++ output ++ ""- where output = outputText result+ where output = resultOutput result -assertOutputDoesNotContain :: String -> Result -> Assertion+assertOutputDoesNotContain :: MonadIO m => String -> Result -> m () assertOutputDoesNotContain needle result = when (needle `isInfixOf` (concatOutput output)) $ assertFailure $ "unexpected: " ++ needle ++ " in output: " ++ output- where output = outputText result+ where output = resultOutput result +assertFindInFile :: MonadIO m => String -> FilePath -> m ()+assertFindInFile needle path =+ liftIO $ withFileContents path+ (\contents ->+ unless (needle `isInfixOf` contents)+ (assertFailure ("expected: " ++ needle ++ "\n" +++ " in file: " ++ path)))+ -- | Replace line breaks with spaces, correctly handling "\r\n". concatOutput :: String -> String concatOutput = unwords . lines . filter ((/=) '\r') +-- | Create a symlink for the duration of the provided action. If the symlink+-- already exists, it is deleted. Does not work on Windows.+withSymlink :: FilePath -> FilePath -> TestM a -> TestM a+#ifdef mingw32_HOST_OS+withSymlink _oldpath _newpath _act =+ error "PackageTests.PackageTester.withSymlink: does not work on Windows!"+#else+withSymlink oldpath newpath act = do+ symlinkExists <- liftIO $ doesFileExist newpath+ when symlinkExists $ liftIO $ removeFile newpath+ bracket_ (liftIO $ createSymbolicLink oldpath newpath)+ (liftIO $ removeFile newpath) act+#endif+ --------------------------------------------------------------------------- Verbosity+-- * Test trees -lookupEnv :: String -> IO (Maybe String)-lookupEnv name =- (fmap Just $ getEnv name)- `E.catch` \ (e :: IOError) ->- if isDoesNotExistError e- then return Nothing- else E.throw e+-- | Monad for creating test trees. The option --enable-all-tests determines+-- whether to filter tests with 'testWhen' and 'testUnless'.+type TestTreeM = WriterT [TestTree] (Reader OptionEnableAllTests) --- TODO: Convert to a "-v" flag instead.-getVerbosity :: IO Verbosity-getVerbosity = do- maybe normal (readEOrFail flagToVerbosity) `fmap` lookupEnv "VERBOSE"+runTestTree :: String -> TestTreeM () -> TestTree+runTestTree name ts = askOption $+ testGroup name . runReader (execWriterT ts)++testTree :: SuiteConfig -> String -> Maybe String -> TestM a -> TestTreeM ()+testTree config name subname m =+ testTree' $ HUnit.testCase name $ runTestM config name subname m++testTree' :: TestTree -> TestTreeM ()+testTree' tc = tell [tc]++-- | Create a test group from the output of the given action.+groupTests :: String -> TestTreeM () -> TestTreeM ()+groupTests name = censor (\ts -> [testGroup name ts])++-- | Apply a function to each top-level test tree.+mapTestTrees :: (TestTree -> TestTree) -> TestTreeM a -> TestTreeM a+mapTestTrees = censor . map++testWhen :: Bool -> TestTreeM () -> TestTreeM ()+testWhen c test = do+ OptionEnableAllTests enableAll <- lift ask+ when (enableAll || c) test++testUnless :: Bool -> TestTreeM () -> TestTreeM ()+testUnless = testWhen . not++unlessWindows :: TestTreeM () -> TestTreeM ()+unlessWindows = testUnless (buildOS == Windows)++hasSharedLibraries :: SuiteConfig -> Bool+hasSharedLibraries config =+ buildOS /= Windows || withGhcVersion config < Version [7,8] []++------------------------------------------------------------------------+-- Verbosity++getVerbosity :: TestM Verbosity+getVerbosity = fmap (suiteVerbosity . fst) ask
− tests/PackageTests/PathsModule/Executable/Check.hs
@@ -1,16 +0,0 @@-module PackageTests.PathsModule.Executable.Check (suite) where--import PackageTests.PackageTester- (PackageSpec(..), assertBuildSucceeded, cabal_build)-import System.FilePath-import Test.HUnit--suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "PathsModule" </> "Executable"- , distPref = Nothing- , configOpts = []- }- result <- cabal_build spec ghcPath- assertBuildSucceeded result
− tests/PackageTests/PathsModule/Library/Check.hs
@@ -1,16 +0,0 @@-module PackageTests.PathsModule.Library.Check (suite) where--import PackageTests.PackageTester- (PackageSpec(..), assertBuildSucceeded, cabal_build)-import System.FilePath-import Test.HUnit--suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "PathsModule" </> "Library"- , distPref = Nothing- , configOpts = []- }- result <- cabal_build spec ghcPath- assertBuildSucceeded result
− tests/PackageTests/PreProcess/Check.hs
@@ -1,16 +0,0 @@-module PackageTests.PreProcess.Check (suite) where--import PackageTests.PackageTester- (PackageSpec(..), assertBuildSucceeded, cabal_build)-import System.FilePath-import Test.HUnit--suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "PreProcess"- , distPref = Nothing- , configOpts = ["--enable-tests", "--enable-benchmarks"]- }- result <- cabal_build spec ghcPath- assertBuildSucceeded result
+ tests/PackageTests/PreProcessExtraSources/Foo.hsc view
@@ -0,0 +1,9 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module Foo where++import Foreign.C.Types++#def int incr(int x) { return x + 1; }++foreign import ccall unsafe "Foo_hsc.h incr"+ incr :: CInt -> CInt
+ tests/PackageTests/PreProcessExtraSources/Main.hs view
@@ -0,0 +1,8 @@+module Main where++import Foo++main :: IO ()+main = do+ let x = incr 4+ return ()
+ tests/PackageTests/PreProcessExtraSources/my.cabal view
@@ -0,0 +1,32 @@+name: PreProcessExtraSources+version: 0.1+license: BSD3+author: Ian Ross+stability: stable+category: PackageTests+build-type: Simple+Cabal-version: >= 1.2++description:+ Check that preprocessors that generate extra C sources are handled.++Library+ exposed-modules: Foo+ build-depends: base++Executable my-executable+ main-is: Main.hs+ other-modules: Foo+ build-depends: base++Test-Suite my-test-suite+ main-is: Main.hs+ type: exitcode-stdio-1.0+ other-modules: Foo+ build-depends: base++Benchmark my-benchmark+ main-is: Main.hs+ type: exitcode-stdio-1.0+ other-modules: Foo+ build-depends: base
− tests/PackageTests/ReexportedModules/Check.hs
@@ -1,41 +0,0 @@-module PackageTests.ReexportedModules.Check where--import Data.Version-import PackageTests.PackageTester-import System.FilePath-import Test.HUnit-import Data.Maybe-import Data.List-import Control.Monad-import Data.Char-import Text.ParserCombinators.ReadP--orFail :: String -> [(a, String)] -> a-orFail err r = case find (all isSpace . snd) r of- Nothing -> error err- Just (i, _) -> i--find' :: (a -> Bool) -> [a] -> Maybe a-find' = find--suite :: FilePath -> Test-suite ghcPath = TestCase $ do- -- ToDo: Turn this into a utility function- (_, _, xs) <- run Nothing ghcPath [] ["--info"]- let compat = (>= Version [7,9] [])- . orFail "could not parse version"- . readP_to_S parseVersion- . snd- . fromJust- . find' ((=="Project version").fst)- . orFail "could not parse ghc --info output"- . reads- $ xs- when compat $ do- let spec = PackageSpec- { directory = "PackageTests" </> "ReexportedModules"- , configOpts = []- , distPref = Nothing- }- result <- cabal_build spec ghcPath- assertBuildSucceeded result
− tests/PackageTests/TemplateHaskell/Check.hs
@@ -1,41 +0,0 @@-module PackageTests.TemplateHaskell.Check where--import PackageTests.PackageTester-import System.FilePath-import Test.HUnit--vanilla :: FilePath -> Test-vanilla ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "TemplateHaskell" </> "vanilla"- , configOpts = []- , distPref = Nothing- }- result <- cabal_build spec ghcPath- assertBuildSucceeded result--profiling :: FilePath -> Test-profiling ghcPath = TestCase $ do- let flags = ["--enable-library-profiling"--- ,"--disable-library-vanilla"- ,"--enable-profiling"]- spec = PackageSpec- { directory = "PackageTests" </> "TemplateHaskell" </> "profiling"- , configOpts = flags- , distPref = Nothing- }- result <- cabal_build spec ghcPath- assertBuildSucceeded result--dynamic :: FilePath -> Test-dynamic ghcPath = TestCase $ do- let flags = ["--enable-shared"--- ,"--disable-library-vanilla"- ,"--enable-executable-dynamic"]- spec = PackageSpec- { directory = "PackageTests" </> "TemplateHaskell" </> "dynamic"- , configOpts = flags- , distPref = Nothing- }- result <- cabal_build spec ghcPath- assertBuildSucceeded result
+ tests/PackageTests/TestNameCollision/child/Child.hs view
@@ -0,0 +1,2 @@+module Child where+import Parent
+ tests/PackageTests/TestNameCollision/child/child.cabal view
@@ -0,0 +1,19 @@+name: child+version: 0.1+description: This defines the colliding detailed-0.9 test suite+license: BSD3+author: Edward Z. Yang+maintainer: ezyang@cs.stanford.edu+build-type: Simple+cabal-version: >=1.10++library+ exposed-modules: Child+ build-depends: base, parent+ default-language: Haskell2010++test-suite parent+ type: detailed-0.9+ test-module: Test+ hs-source-dirs: tests+ build-depends: base, Cabal, child
+ tests/PackageTests/TestNameCollision/child/tests/Test.hs view
@@ -0,0 +1,13 @@+module Test where++import Distribution.TestSuite+import Child++tests :: IO [Test]+tests = return $ [Test $ TestInstance+ { run = return (Finished Pass)+ , name = "test"+ , tags = []+ , options = []+ , setOption = \_ _-> Left "No Options"+ }]
+ tests/PackageTests/TestNameCollision/parent/Parent.hs view
@@ -0,0 +1,1 @@+module Parent where
+ tests/PackageTests/TestNameCollision/parent/parent.cabal view
@@ -0,0 +1,13 @@+name: parent+version: 0.1+description: This package is what the test suite is going to collide with+license: BSD3+author: Edward Z. Yang+maintainer: ezyang@cs.stanford.edu+build-type: Simple+cabal-version: >=1.10++library+ exposed-modules: Parent+ build-depends: base+ default-language: Haskell2010
− tests/PackageTests/TestOptions/Check.hs
@@ -1,26 +0,0 @@-module PackageTests.TestOptions.Check where--import PackageTests.PackageTester-import System.FilePath-import Test.HUnit--suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let spec = PackageSpec- { directory = "PackageTests" </> "TestOptions"- , configOpts = ["--enable-tests"]- , distPref = Nothing- }- _ <- cabal_build spec ghcPath- result <- cabal_test spec [] ["--test-options=1 2 3"] ghcPath- let message = "\"cabal test\" did not pass the correct options to the "- ++ "test executable with \"--test-options\""- assertEqual message True $ successful result- result' <- cabal_test spec [] [ "--test-option=1"- , "--test-option=2"- , "--test-option=3"- ]- ghcPath- let message' = "\"cabal test\" did not pass the correct options to the "- ++ "test executable with \"--test-option\""- assertEqual message' True $ successful result'
tests/PackageTests/TestStanza/Check.hs view
@@ -1,53 +1,29 @@ module PackageTests.TestStanza.Check where -import Test.HUnit-import System.FilePath-import qualified Data.Map as Map import PackageTests.PackageTester+ import Distribution.Version-import Distribution.PackageDescription.Parse (readPackageDescription)-import Distribution.PackageDescription.Configuration- (finalizePackageDescription)-import Distribution.Package (PackageName(..), Dependency(..))+import Distribution.Simple.LocalBuildInfo+import Distribution.Package import Distribution.PackageDescription- ( PackageDescription(..), BuildInfo(..), TestSuite(..)- , TestSuiteInterface(..), emptyBuildInfo, emptyTestSuite- , defaultRenaming)-import Distribution.Verbosity (silent)-import Distribution.System (buildPlatform)-import Distribution.Compiler- ( CompilerId(..), CompilerFlavor(..), unknownCompilerInfo, AbiTag(..) )-import Distribution.Text -suite :: FilePath -> Test-suite ghcPath = TestCase $ do- let dir = "PackageTests" </> "TestStanza"- pdFile = dir </> "my" <.> "cabal"- spec = PackageSpec- { directory = dir- , configOpts = []- , distPref = Nothing- }- result <- cabal_configure spec ghcPath- assertOutputDoesNotContain "unknown section type" result- genPD <- readPackageDescription silent pdFile- let compiler = unknownCompilerInfo (CompilerId GHC $ Version [6, 12, 2] []) NoAbiTag- anticipatedTestSuite = emptyTestSuite+suite :: TestM ()+suite = do+ assertOutputDoesNotContain "unknown section type"+ =<< cabal' "configure" []+ dist_dir <- distDir+ lbi <- liftIO $ getPersistBuildConfig dist_dir+ let anticipatedTestSuite = emptyTestSuite { testName = "dummy" , testInterface = TestSuiteExeV10 (Version [1,0] []) "dummy.hs" , testBuildInfo = emptyBuildInfo { targetBuildDepends = [ Dependency (PackageName "base") anyVersion ]- , targetBuildRenaming =- Map.singleton (PackageName "base") defaultRenaming , hsSourceDirs = ["."] } , testEnabled = False }- case finalizePackageDescription [] (const True) buildPlatform compiler [] genPD of- Left xs -> let depMessage = "should not have missing dependencies:\n" ++- (unlines $ map (show . disp) xs)- in assertEqual depMessage True False- Right (f, _) -> let gotTest = head $ testSuites f- in assertEqual "parsed test-suite stanza does not match anticipated"- gotTest anticipatedTestSuite+ gotTestSuite = head $ testSuites (localPkgDescr lbi)+ assertEqual "parsed test-suite stanza does not match anticipated"+ anticipatedTestSuite gotTestSuite+ return ()
− tests/PackageTests/TestSuiteExeV10/Check.hs
@@ -1,147 +0,0 @@-module PackageTests.TestSuiteExeV10.Check (checks) where--import qualified Control.Exception as E (IOException, catch)-import Control.Monad (when)-import Data.Maybe (catMaybes)-import System.Directory ( doesFileExist )-import System.FilePath-import qualified Test.Framework as TF-import Test.Framework (testGroup)-import Test.Framework.Providers.HUnit (hUnitTestToTests)-import Test.HUnit hiding ( path )--import Distribution.Compiler (CompilerFlavor(..), CompilerId(..))-import Distribution.PackageDescription (package)-import Distribution.Simple.Compiler (compilerId)-import Distribution.Simple.Configure (getPersistBuildConfig)-import Distribution.Simple.LocalBuildInfo (compiler, localPkgDescr, pkgKey)-import Distribution.Simple.Hpc-import Distribution.Simple.Program.Builtin (hpcProgram)-import Distribution.Simple.Program.Db- ( emptyProgramDb, configureProgram, requireProgramVersion )-import Distribution.Text (display)-import qualified Distribution.Verbosity as Verbosity-import Distribution.Version (Version(..), orLaterVersion)--import PackageTests.PackageTester--checks :: FilePath -> [TF.Test]-checks ghcPath =- [ hunit "Test" $ checkTest ghcPath ]- ++ hpcTestMatrix ghcPath ++- [ hunit "TestNoHpc/NoTix" $ checkTestNoHpcNoTix ghcPath- , hunit "TestNoHpc/NoMarkup" $ checkTestNoHpcNoMarkup ghcPath- ]--hpcTestMatrix :: FilePath -> [TF.Test]-hpcTestMatrix ghcPath = do- libProf <- [True, False]- exeProf <- [True, False]- exeDyn <- [True, False]- shared <- [True, False]- let name = concat- [ "WithHpc-"- , if libProf then "LibProf" else ""- , if exeProf then "ExeProf" else ""- , if exeDyn then "ExeDyn" else ""- , if shared then "Shared" else ""- ]- enable cond flag- | cond = Just $ "--enable-" ++ flag- | otherwise = Nothing- opts = catMaybes- [ enable libProf "library-profiling"- , enable exeProf "profiling"- , enable exeDyn "executable-dynamic"- , enable shared "shared"- ]- return $ hunit name $ checkTestWithHpc ghcPath name opts--dir :: FilePath-dir = "PackageTests" </> "TestSuiteExeV10"--checkTest :: FilePath -> Test-checkTest ghcPath = TestCase $ buildAndTest ghcPath "Default" [] []--shouldExist :: FilePath -> Assertion-shouldExist path = doesFileExist path >>= assertBool (path ++ " should exist")--shouldNotExist :: FilePath -> Assertion-shouldNotExist path =- doesFileExist path >>= assertBool (path ++ " should exist") . not---- | Ensure that both .tix file and markup are generated if coverage is enabled.-checkTestWithHpc :: FilePath -> String -> [String] -> Test-checkTestWithHpc ghcPath name extraOpts = TestCase $ do- isCorrectVersion <- correctHpcVersion- when isCorrectVersion $ do- let distPref' = dir </> "dist-" ++ name- buildAndTest ghcPath name [] ("--enable-coverage" : extraOpts)- lbi <- getPersistBuildConfig distPref'- let way = guessWay lbi- CompilerId comp version = compilerId (compiler lbi)- subdir- | comp == GHC && version >= Version [7, 10] [] =- display (pkgKey lbi)- | otherwise = display (package $ localPkgDescr lbi)- mapM_ shouldExist- [ mixDir distPref' way "my-0.1" </> subdir </> "Foo.mix"- , mixDir distPref' way "test-Foo" </> "Main.mix"- , tixFilePath distPref' way "test-Foo"- , htmlDir distPref' way "test-Foo" </> "hpc_index.html"- ]---- | Ensures that even if -fhpc is manually provided no .tix file is output.-checkTestNoHpcNoTix :: FilePath -> Test-checkTestNoHpcNoTix ghcPath = TestCase $ do- buildAndTest ghcPath "NoHpcNoTix" []- [ "--ghc-option=-fhpc"- , "--ghc-option=-hpcdir"- , "--ghc-option=dist-NoHpcNoTix/hpc/vanilla" ]- lbi <- getPersistBuildConfig (dir </> "dist-NoHpcNoTix")- let way = guessWay lbi- shouldNotExist $ tixFilePath (dir </> "dist-NoHpcNoTix") way "test-Foo"---- | Ensures that even if a .tix file happens to be left around--- markup isn't generated.-checkTestNoHpcNoMarkup :: FilePath -> Test-checkTestNoHpcNoMarkup ghcPath = TestCase $ do- let tixFile = tixFilePath "dist-NoHpcNoMarkup" Vanilla "test-Foo"- buildAndTest ghcPath "NoHpcNoMarkup"- [("HPCTIXFILE", Just tixFile)]- [ "--ghc-option=-fhpc"- , "--ghc-option=-hpcdir"- , "--ghc-option=dist-NoHpcNoMarkup/hpc/vanilla" ]- shouldNotExist $ htmlDir (dir </> "dist-NoHpcNoMarkup") Vanilla "test-Foo" </> "hpc_index.html"---- | Build and test a package and ensure that both were successful.------ The flag "--enable-tests" is provided in addition to the given flags.-buildAndTest :: FilePath -> String -> [(String, Maybe String)] -> [String] -> IO ()-buildAndTest ghcPath name envOverrides flags = do- let spec = PackageSpec- { directory = dir- , distPref = Just $ "dist-" ++ name- , configOpts = "--enable-tests" : flags- }- buildResult <- cabal_build spec ghcPath- assertBuildSucceeded buildResult- testResult <- cabal_test spec envOverrides [] ghcPath- assertTestSucceeded testResult--hunit :: TF.TestName -> Test -> TF.Test-hunit name = testGroup name . hUnitTestToTests---- | Checks for a suitable HPC version for testing.-correctHpcVersion :: IO Bool-correctHpcVersion = do- let programDb' = emptyProgramDb- let verbosity = Verbosity.normal- let verRange = orLaterVersion (Version [0,7] [])- programDb <- configureProgram verbosity hpcProgram programDb'- (requireProgramVersion verbosity hpcProgram verRange programDb- >> return True) `catchIO` (\_ -> return False)- where- -- Distribution.Compat.Exception is hidden.- catchIO :: IO a -> (E.IOException -> IO a) -> IO a- catchIO = E.catch
− tests/PackageTests/TestSuiteExeV10/Foo.hs
@@ -1,4 +0,0 @@-module Foo where--fooTest :: [String] -> Bool-fooTest _ = True
− tests/PackageTests/TestSuiteExeV10/my.cabal
@@ -1,15 +0,0 @@-name: my-version: 0.1-license: BSD3-cabal-version: >= 1.9.2-build-type: Simple--library- exposed-modules: Foo- build-depends: base--test-suite test-Foo- type: exitcode-stdio-1.0- hs-source-dirs: tests- main-is: test-Foo.hs- build-depends: base, my
− tests/PackageTests/TestSuiteExeV10/tests/test-Foo.hs
@@ -1,8 +0,0 @@-module Main where--import Foo-import System.Exit--main :: IO ()-main | fooTest [] = exitSuccess- | otherwise = exitFailure
+ tests/PackageTests/TestSuiteTests/ExeV10/Check.hs view
@@ -0,0 +1,129 @@+module PackageTests.TestSuiteTests.ExeV10.Check (tests) where++import qualified Control.Exception as E (IOException, catch)+import Control.Monad (forM_, liftM4, when)+import Data.Maybe (catMaybes)+import System.FilePath+import Test.Tasty.HUnit (testCase)++import Distribution.Compiler (CompilerFlavor(..), CompilerId(..))+import Distribution.PackageDescription (package)+import Distribution.Simple.Compiler (compilerId)+import Distribution.Simple.LocalBuildInfo (compiler, localPkgDescr, localCompatPackageKey)+import Distribution.Simple.Hpc+import Distribution.Simple.Program.Builtin (hpcProgram)+import Distribution.Simple.Program.Db+ ( emptyProgramDb, configureProgram, requireProgramVersion )+import Distribution.Text (display)+import qualified Distribution.Verbosity as Verbosity+import Distribution.Version (Version(..), orLaterVersion)++import PackageTests.PackageTester++tests :: SuiteConfig -> TestTreeM ()+tests config = do+ -- TODO: hierarchy and subnaming is a little unfortunate+ tc "Test" "Default" $ do+ cabal_build ["--enable-tests"]+ -- This one runs both tests, including the very LONG Foo+ -- test which prints a lot of output+ cabal "test" ["--show-details=direct"]+ groupTests "WithHpc" $ hpcTestMatrix config+ groupTests "WithoutHpc" $ do+ -- Ensures that even if -fhpc is manually provided no .tix file is output.+ tc "NoTix" "NoHpcNoTix" $ do+ dist_dir <- distDir+ cabal_build+ [ "--enable-tests"+ , "--ghc-option=-fhpc"+ , "--ghc-option=-hpcdir"+ , "--ghc-option=" ++ dist_dir ++ "/hpc/vanilla" ]+ cabal "test" ["test-Short", "--show-details=direct"]+ lbi <- liftIO $ getPersistBuildConfig dist_dir+ let way = guessWay lbi+ shouldNotExist $ tixFilePath dist_dir way "test-Short"+ -- Ensures that even if a .tix file happens to be left around+ -- markup isn't generated.+ tc "NoMarkup" "NoHpcNoMarkup" $ do+ dist_dir <- distDir+ let tixFile = tixFilePath dist_dir Vanilla "test-Short"+ withEnv [("HPCTIXFILE", Just tixFile)] $ do+ cabal_build+ [ "--enable-tests"+ , "--ghc-option=-fhpc"+ , "--ghc-option=-hpcdir"+ , "--ghc-option=" ++ dist_dir ++ "/hpc/vanilla" ]+ cabal "test" ["test-Short", "--show-details=direct"]+ shouldNotExist $ htmlDir dist_dir Vanilla "test-Short" </> "hpc_index.html"+ where+ tc :: String -> String -> TestM a -> TestTreeM ()+ tc name subname m+ = testTree' $ testCase name+ (runTestM config "TestSuiteTests/ExeV10" (Just subname) m)++hpcTestMatrix :: SuiteConfig -> TestTreeM ()+hpcTestMatrix config = forM_ (choose4 [True, False]) $+ \(libProf, exeProf, exeDyn, shared) -> do+ let name | null suffixes = "Vanilla"+ | otherwise = intercalate "-" suffixes+ where+ suffixes = catMaybes+ [ if libProf then Just "LibProf" else Nothing+ , if exeProf then Just "ExeProf" else Nothing+ , if exeDyn then Just "ExeDyn" else Nothing+ , if shared then Just "Shared" else Nothing+ ]+ opts = catMaybes+ [ enable libProf "library-profiling"+ , enable exeProf "profiling"+ , enable exeDyn "executable-dynamic"+ , enable shared "shared"+ ]+ where+ enable cond flag+ | cond = Just $ "--enable-" ++ flag+ | otherwise = Nothing+ -- Ensure that both .tix file and markup are generated if coverage+ -- is enabled.+ testUnless ((exeDyn || shared) && not (hasSharedLibraries config)) $+ tc name ("WithHpc-" ++ name) $ do+ isCorrectVersion <- liftIO $ correctHpcVersion+ when isCorrectVersion $ do+ dist_dir <- distDir+ cabal_build ("--enable-tests" : "--enable-coverage" : opts)+ cabal "test" ["test-Short", "--show-details=direct"]+ lbi <- liftIO $ getPersistBuildConfig dist_dir+ let way = guessWay lbi+ CompilerId comp version = compilerId (compiler lbi)+ subdir+ | comp == GHC && version >= Version [7, 10] [] =+ localCompatPackageKey lbi+ | otherwise = display (package $ localPkgDescr lbi)+ mapM_ shouldExist+ [ mixDir dist_dir way "my-0.1" </> subdir </> "Foo.mix"+ , mixDir dist_dir way "test-Short" </> "Main.mix"+ , tixFilePath dist_dir way "test-Short"+ , htmlDir dist_dir way "test-Short" </> "hpc_index.html"+ ]+ where+ tc :: String -> String -> TestM a -> TestTreeM ()+ tc name subname m+ = testTree' $ testCase name+ (runTestM config "TestSuiteTests/ExeV10" (Just subname) m)++ choose4 :: [a] -> [(a, a, a, a)]+ choose4 xs = liftM4 (,,,) xs xs xs xs++-- | Checks for a suitable HPC version for testing.+correctHpcVersion :: IO Bool+correctHpcVersion = do+ let programDb' = emptyProgramDb+ let verbosity = Verbosity.normal+ let verRange = orLaterVersion (Version [0,7] [])+ programDb <- configureProgram verbosity hpcProgram programDb'+ (requireProgramVersion verbosity hpcProgram verRange programDb+ >> return True) `catchIO` (\_ -> return False)+ where+ -- Distribution.Compat.Exception is hidden.+ catchIO :: IO a -> (E.IOException -> IO a) -> IO a+ catchIO = E.catch
+ tests/PackageTests/TestSuiteTests/ExeV10/Foo.hs view
@@ -0,0 +1,4 @@+module Foo where++fooTest :: [String] -> Bool+fooTest _ = True
+ tests/PackageTests/TestSuiteTests/ExeV10/my.cabal view
@@ -0,0 +1,21 @@+name: my+version: 0.1+license: BSD3+cabal-version: >= 1.9.2+build-type: Simple++library+ exposed-modules: Foo+ build-depends: base++test-suite test-Foo+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ main-is: test-Foo.hs+ build-depends: base, my++test-suite test-Short+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ main-is: test-Short.hs+ build-depends: base, my
+ tests/PackageTests/TestSuiteTests/ExeV10/tests/test-Foo.hs view
@@ -0,0 +1,12 @@+module Main where++import Foo+import System.Exit+import Control.Monad++main :: IO ()+main | fooTest [] = do+ -- Make sure that the output buffer is drained+ replicateM 10000 $ putStrLn "The quick brown fox jumps over the lazy dog"+ exitSuccess+ | otherwise = exitFailure
+ tests/PackageTests/TestSuiteTests/ExeV10/tests/test-Short.hs view
@@ -0,0 +1,11 @@+module Main where++import Foo+import System.Exit+import Control.Monad++main :: IO ()+main | fooTest [] = do+ replicateM 5 $ putStrLn "The quick brown fox jumps over the lazy dog"+ exitSuccess+ | otherwise = exitFailure
+ tests/PackageTests/TestSuiteTests/LibV09/Lib.hs view
@@ -0,0 +1,11 @@+module Lib where++import Distribution.TestSuite++nullt x = Test $ TestInstance+ { run = return $ Finished (Fail "no reason")+ , name = "test " ++ show x+ , tags = []+ , options = []+ , setOption = \_ _-> Left "No Options"+ }
+ tests/PackageTests/TestSuiteTests/LibV09/LibV09.cabal view
@@ -0,0 +1,21 @@+name: LibV09+version: 0.1+cabal-version: >= 1.2+license: BSD3+author: Thomas Tuegel+stability: stable+category: PackageTests+build-type: Simple+cabal-version: >= 1.9.2++description: Check type detailed-0.9 test suites.++library+ exposed-modules: Lib+ build-depends: base, Cabal++test-suite LibV09-Deadlock+ type: detailed-0.9+ hs-source-dirs: tests+ test-module: Deadlock+ build-depends: base, Cabal, LibV09
+ tests/PackageTests/TestSuiteTests/LibV09/tests/Deadlock.hs view
@@ -0,0 +1,8 @@+module Deadlock where++import Distribution.TestSuite++import Lib++tests :: IO [Test]+tests = return [nullt x | x <- [1 .. 1000]]
+ tests/PackageTests/Tests.hs view
@@ -0,0 +1,307 @@+module PackageTests.Tests(tests) where++import PackageTests.PackageTester++import qualified PackageTests.BenchmarkStanza.Check+import qualified PackageTests.TestStanza.Check+import qualified PackageTests.DeterministicAr.Check+import qualified PackageTests.TestSuiteTests.ExeV10.Check++import Control.Monad++import Data.Version+import Test.Tasty (mkTimeout, localOption)+import Test.Tasty.HUnit (testCase)++tests :: SuiteConfig -> TestTreeM ()+tests config = do++ ---------------------------------------------------------------------+ -- * External tests++ -- Test that Cabal parses 'benchmark' sections correctly+ tc "BenchmarkStanza" PackageTests.BenchmarkStanza.Check.suite++ -- Test that Cabal parses 'test' sections correctly+ tc "TestStanza" PackageTests.TestStanza.Check.suite++ -- Test that Cabal determinstically generates object archives+ tc "DeterministicAr" PackageTests.DeterministicAr.Check.suite++ ---------------------------------------------------------------------+ -- * Test suite tests++ groupTests "TestSuiteTests" $ do++ -- Test exitcode-stdio-1.0 test suites (and HPC)+ groupTests "ExeV10"+ (PackageTests.TestSuiteTests.ExeV10.Check.tests config)++ -- Test detailed-0.9 test suites+ groupTests "LibV09" $+ let+ tcs :: FilePath -> TestM a -> TestTreeM ()+ tcs name m+ = testTree' $ testCase name (runTestM config+ "TestSuiteTests/LibV09" (Just name) m)+ in do+ -- Test if detailed-0.9 builds correctly+ tcs "Build" $ cabal_build ["--enable-tests"]++ -- Tests for #2489, stdio deadlock+ mapTestTrees (localOption (mkTimeout $ 10 ^ (8 :: Int)))+ . tcs "Deadlock" $ do+ cabal_build ["--enable-tests"]+ shouldFail $ cabal "test" []++ ---------------------------------------------------------------------+ -- * Inline tests++ -- Test if exitcode-stdio-1.0 benchmark builds correctly+ tc "BenchmarkExeV10" $ cabal_build ["--enable-benchmarks"]++ -- Test --benchmark-option(s) flags on ./Setup bench+ tc "BenchmarkOptions" $ do+ cabal_build ["--enable-benchmarks"]+ cabal "bench" [ "--benchmark-options=1 2 3" ]+ cabal "bench" [ "--benchmark-option=1"+ , "--benchmark-option=2"+ , "--benchmark-option=3"+ ]++ -- Test --test-option(s) flags on ./Setup test+ tc "TestOptions" $ do+ cabal_build ["--enable-tests"]+ cabal "test" ["--test-options=1 2 3"]+ cabal "test" [ "--test-option=1"+ , "--test-option=2"+ , "--test-option=3"+ ]++ -- Test attempt to have executable depend on internal+ -- library, but cabal-version is too old.+ tc "BuildDeps/InternalLibrary0" $ do+ r <- shouldFail $ cabal' "configure" []+ -- Should tell you how to enable the desired behavior+ let sb = "library which is defined within the same package."+ assertOutputContains sb r++ -- Test executable depends on internal library.+ tc "BuildDeps/InternalLibrary1" $ cabal_build []++ -- Test that internal library is preferred to an installed on+ -- with the same name and version+ tc "BuildDeps/InternalLibrary2" $ internal_lib_test "internal"++ -- Test that internal library is preferred to an installed on+ -- with the same name and LATER version+ tc "BuildDeps/InternalLibrary3" $ internal_lib_test "internal"++ -- Test that an explicit dependency constraint which doesn't+ -- match the internal library causes us to use external library+ tc "BuildDeps/InternalLibrary4" $ internal_lib_test "installed"++ -- Test "old build-dep behavior", where we should get the+ -- same package dependencies on all targets if cabal-version+ -- is sufficiently old.+ tc "BuildDeps/SameDepsAllRound" $ cabal_build []++ -- Test "new build-dep behavior", where each target gets+ -- separate dependencies. This tests that an executable+ -- dep does not leak into the library.+ tc "BuildDeps/TargetSpecificDeps1" $ do+ cabal "configure" []+ r <- shouldFail $ cabal' "build" []+ assertRegex "error should be in MyLibrary.hs" "^MyLibrary.hs:" r+ assertRegex+ "error should be \"Could not find module `Text\\.PrettyPrint\""+ "(Could not find module|Failed to load interface for).*Text\\.PrettyPrint" r++ -- This is a control on TargetSpecificDeps1; it should+ -- succeed.+ tc "BuildDeps/TargetSpecificDeps2" $ cabal_build []++ -- Test "new build-dep behavior", where each target gets+ -- separate dependencies. This tests that an library+ -- dep does not leak into the executable.+ tc "BuildDeps/TargetSpecificDeps3" $ do+ cabal "configure" []+ r <- shouldFail $ cabal' "build" []+ assertRegex "error should be in lemon.hs" "^lemon.hs:" r+ assertRegex+ "error should be \"Could not find module `Text\\.PrettyPrint\""+ "(Could not find module|Failed to load interface for).*Text\\.PrettyPrint" r++ -- Test that Paths module is generated and available for executables.+ tc "PathsModule/Executable" $ cabal_build []++ -- Test that Paths module is generated and available for libraries.+ tc "PathsModule/Library" $ cabal_build []++ -- Check that preprocessors (hsc2hs) are run+ tc "PreProcess" $ cabal_build ["--enable-tests", "--enable-benchmarks"]++ -- Check that preprocessors that generate extra C sources are handled+ tc "PreProcessExtraSources" $ cabal_build ["--enable-tests",+ "--enable-benchmarks"]++ -- Test building a vanilla library/executable which uses Template Haskell+ tc "TemplateHaskell/vanilla" $ cabal_build []++ -- Test building a profiled library/executable which uses Template Haskell+ -- (Cabal has to build the non-profiled version first)+ tc "TemplateHaskell/profiling" $ cabal_build ["--enable-library-profiling",+ "--enable-profiling"]++ -- Test building a dynamic library/executable which uses Template+ -- Haskell+ testWhen (hasSharedLibraries config) $+ tc "TemplateHaskell/dynamic" $ cabal_build ["--enable-shared",+ "--enable-executable-dynamic"]++ -- Test building an executable whose main() function is defined in a C+ -- file+ tc "CMain" $ cabal_build []++ -- Test build when the library is empty, for #1241+ tc "EmptyLib" $+ withPackage "empty" $ cabal_build []++ -- Test that "./Setup haddock" works correctly+ tc "Haddock" $ do+ dist_dir <- distDir+ let haddocksDir = dist_dir </> "doc" </> "html" </> "Haddock"+ cabal "configure" []+ cabal "haddock" []+ let docFiles+ = map (haddocksDir </>)+ ["CPP.html", "Literate.html", "NoCPP.html", "Simple.html"]+ mapM_ (assertFindInFile "For hiding needles.") docFiles++ -- Test that Haddock with a newline in synopsis works correctly, #3004+ tc "HaddockNewline" $ do+ cabal "configure" []+ cabal "haddock" []++ -- Test that Cabal properly orders GHC flags passed to GHC (when+ -- there are multiple ghc-options fields.)+ tc "OrderFlags" $ cabal_build []++ -- Test that reexported modules build correctly+ -- TODO: should also test that they import OK!+ tc "ReexportedModules" $ do+ whenGhcVersion (>= Version [7,9] []) $ cabal_build []++ -- Test that Cabal computes different IPIDs when the source changes.+ tc "UniqueIPID" . withPackageDb $ do+ withPackage "P1" $ cabal "configure" []+ withPackage "P2" $ cabal "configure" []+ withPackage "P1" $ cabal "build" []+ withPackage "P1" $ cabal "build" [] -- rebuild should work+ r1 <- withPackage "P1" $ cabal' "register" ["--print-ipid", "--inplace"]+ withPackage "P2" $ cabal "build" []+ r2 <- withPackage "P2" $ cabal' "register" ["--print-ipid", "--inplace"]+ let exIPID s = takeWhile (/= '\n') $+ head . filter (isPrefixOf $ "UniqueIPID-0.1-") $ (tails s)+ when ((exIPID $ resultOutput r1) == (exIPID $ resultOutput r2)) $+ assertFailure $ "cabal has not calculated different Installed " +++ "package ID when source is changed."++ tc "DuplicateModuleName" $ do+ cabal_build ["--enable-tests"]+ r1 <- shouldFail $ cabal' "test" ["foo"]+ assertOutputContains "test B" r1+ assertOutputContains "test A" r1+ r2 <- shouldFail $ cabal' "test" ["foo2"]+ assertOutputContains "test C" r2+ assertOutputContains "test A" r2++ tc "TestNameCollision" $ do+ withPackageDb $ do+ withPackage "parent" $ cabal_install []+ withPackage "child" $ do+ cabal_build ["--enable-tests"]+ cabal "test" []++ -- Test that '--allow-newer' works via the 'Setup.hs configure' interface.+ tc "AllowNewer" $ do+ shouldFail $ cabal "configure" []+ cabal "configure" ["--allow-newer"]+ shouldFail $ cabal "configure" ["--allow-newer=baz,quux"]+ cabal "configure" ["--allow-newer=base", "--allow-newer=baz,quux"]+ cabal "configure" ["--allow-newer=bar", "--allow-newer=base,baz"+ ,"--allow-newer=quux"]+ shouldFail $ cabal "configure" ["--enable-tests"]+ cabal "configure" ["--enable-tests", "--allow-newer"]+ shouldFail $ cabal "configure" ["--enable-benchmarks"]+ cabal "configure" ["--enable-benchmarks", "--allow-newer"]+ shouldFail $ cabal "configure" ["--enable-benchmarks", "--enable-tests"]+ cabal "configure" ["--enable-benchmarks", "--enable-tests"+ ,"--allow-newer"]+ shouldFail $ cabal "configure" ["--allow-newer=Foo:base"]+ shouldFail $ cabal "configure" ["--allow-newer=Foo:base"+ ,"--enable-tests", "--enable-benchmarks"]+ cabal "configure" ["--allow-newer=AllowNewer:base"]+ cabal "configure" ["--allow-newer=AllowNewer:base"+ ,"--allow-newer=Foo:base"]+ cabal "configure" ["--allow-newer=AllowNewer:base"+ ,"--allow-newer=Foo:base"+ ,"--enable-tests", "--enable-benchmarks"]++ -- Test that Cabal can choose flags to disable building a component when that+ -- component's dependencies are unavailable. The build should succeed without+ -- requiring the component's dependencies or imports.+ tc "BuildableField" $ do+ r <- cabal' "configure" ["-v"]+ assertOutputContains "Flags chosen: build-exe=False" r+ cabal "build" []++ -- TODO: Enable these tests on Windows+ unlessWindows $ do+ tc "GhcPkgGuess/SameDirectory" $ ghc_pkg_guess "ghc"+ tc "GhcPkgGuess/SameDirectoryVersion" $ ghc_pkg_guess "ghc-7.10"+ tc "GhcPkgGuess/SameDirectoryGhcVersion" $ ghc_pkg_guess "ghc-7.10"++ unlessWindows $ do+ tc "GhcPkgGuess/Symlink" $ do+ -- We don't want to distribute a tarball with symlinks. See #3190.+ withSymlink "bin/ghc"+ "tests/PackageTests/GhcPkgGuess/Symlink/ghc" $+ ghc_pkg_guess "ghc"++ tc "GhcPkgGuess/SymlinkVersion" $ do+ withSymlink "bin/ghc-7.10"+ "tests/PackageTests/GhcPkgGuess/SymlinkVersion/ghc" $+ ghc_pkg_guess "ghc"++ tc "GhcPkgGuess/SymlinkGhcVersion" $ do+ withSymlink "bin/ghc-7.10"+ "tests/PackageTests/GhcPkgGuess/SymlinkGhcVersion/ghc" $+ ghc_pkg_guess "ghc"++ where+ ghc_pkg_guess bin_name = do+ cwd <- packageDir+ with_ghc <- getWithGhcPath+ r <- withEnv [("WITH_GHC", Just with_ghc)]+ . shouldFail $ cabal' "configure" ["-w", cwd </> bin_name]+ assertOutputContains "is version 9999999" r+ return ()++ -- Shared test function for BuildDeps/InternalLibrary* tests.+ internal_lib_test expect = withPackageDb $ do+ withPackage "to-install" $ cabal_install []+ cabal_build []+ r <- runExe' "lemon" []+ assertEqual+ ("executable should have linked with the " ++ expect ++ " library")+ ("foo foo myLibFunc " ++ expect)+ (concatOutput (resultOutput r))++ assertRegex :: String -> String -> Result -> TestM ()+ assertRegex msg regex r = let out = resultOutput r+ in assertBool (msg ++ ",\nactual output:\n" ++ out)+ (out =~ regex)++ tc :: FilePath -> TestM a -> TestTreeM ()+ tc name = testTree config name Nothing
+ tests/PackageTests/UniqueIPID/P1/M.hs view
@@ -0,0 +1,3 @@+module M(m) where++m = print "1"
+ tests/PackageTests/UniqueIPID/P1/my.cabal view
@@ -0,0 +1,15 @@+name: UniqueIPID+version: 0.1+license: BSD3+author: Vishal Agrawal+stability: stable+category: PackageTests+build-type: Simple+Cabal-version: >= 1.2++description:+ Check that Cabal generates unique IPID based on source.++Library+ exposed-modules: M+ build-depends: base
+ tests/PackageTests/UniqueIPID/P2/M.hs view
@@ -0,0 +1,3 @@+module M(m) where++m = print "2"
+ tests/PackageTests/UniqueIPID/P2/my.cabal view
@@ -0,0 +1,15 @@+name: UniqueIPID+version: 0.1+license: BSD3+author: Vishal Agrawal+stability: stable+category: PackageTests+build-type: Simple+Cabal-version: >= 1.2++description:+ Check that Cabal generates unique IPID based on source.++Library+ exposed-modules: M+ build-depends: base, containers
+ tests/PackageTests/multInst/my.cabal view
@@ -0,0 +1,16 @@+name: Haddock+version: 0.1+license: BSD3+author: Iain Nicol+stability: stable+category: PackageTests+build-type: Simple+Cabal-version: >= 1.2++description:+ Check that Cabal successfully invokes Haddock.++Library+ exposed-modules: CPP, Literate, NoCPP, Simple+ other-extensions: CPP+ build-depends: base
tests/README.md view
@@ -8,23 +8,27 @@ of Cabal's build process in [PackageTests/PackageTester.hs]; have a look at an existing test case to see how they are used. -It is important that package tests use the in-place version of Cabal-rather than the system version. Several long-standing bugs in the test-suite were caused by testing the system (rather than the newly compiled)-version of Cabal. There are two places where the system Cabal can-accidentally be invoked:+In order to run the tests, `PackageTests` needs to know where the inplace+copy of Cabal being tested is, as well as some information which was+used to configure it. By default, `PackageTests` tries to look at the+`LocalBuildInfo`, but if the format of `LocalBuildInfo` has changed+between the version of Cabal which ran the configure step, and the+version of Cabal we are testing against, this may fail. In that+case, you can manually specify the information we need using+the following environment variables: -1. Compiling `Setup.hs`. `runghc` needs to be told about the in-place- package database. This issue should be solved for all future package- tests; see `compileSetup` in [PackageTests/PackageTester.hs].+* `CABAL_PACKAGETESTS_GHC` is the path to the GHC you compiled Cabal with+* `CABAL_PACKAGETESTS_GHC_PKG` is the path to the ghc-pkg associated with this GHC+* `CABAL_PACKAGETESTS_HADDOCK` is the path to the haddock associated with this GHC+* `CABAL_PACKAGETESTS_GHC_VERSION` is the version of your GHC+* `CABAL_PACKAGETESTS_DB_STACK` is a PATH-style list of package database paths,+ `clear`, `global` and `user`. Each component of the list is+ interpreted the same way as Cabal's `-package-db` flag. This list+ must contain the copy of Cabal you are planning to test against+ (as well as its transitive dependencies). -2. Compiling a package which depends on Cabal. In particular, packages- with the [detailed]-type test suites depend on the Cabal library- directly, so it is important that they are configured to use the- in-place package database. The test suite already creates a stub- `PackageSpec` for this case; see- [PackageTests/BuildTestSuiteDetailedV09/Check.hs] to see how it is- used.+If you can successfully run the test suite, we'll print out examples+of all of these values for you under "Environment". [PackageTests]: PackageTests [HUnit]: http://hackage.haskell.org/package/HUnit
+ tests/Test/Laws.hs view
@@ -0,0 +1,79 @@+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}+module Test.Laws where++import Prelude hiding (Num((+), (*)))+import Data.Monoid (Monoid(..), Endo(..))+import qualified Data.Foldable as Foldable++idempotent_unary f x = f fx == fx where fx = f x++-- Basic laws on binary operators++idempotent_binary (+) x = x + x == x++commutative (+) x y = x + y == y + x++associative (+) x y z = (x + y) + z == x + (y + z)++distributive_left (*) (+) x y z = x * (y + z) == (x * y) + (x * z)++distributive_right (*) (+) x y z = (y + z) * x == (y * x) + (z * x)+++-- | The first 'fmap' law+--+-- > fmap id == id+--+fmap_1 :: (Eq (f a), Functor f) => f a -> Bool+fmap_1 x = fmap id x == x++-- | The second 'fmap' law+--+-- > fmap (f . g) == fmap f . fmap g+--+fmap_2 :: (Eq (f c), Functor f) => (b -> c) -> (a -> b) -> f a -> Bool+fmap_2 f g x = fmap (f . g) x == (fmap f . fmap g) x+++-- | The monoid identity law, 'mempty' is a left and right identity of+-- 'mappend':+--+-- > mempty `mappend` x = x+-- > x `mappend` mempty = x+--+monoid_1 :: (Eq a, Data.Monoid.Monoid a) => a -> Bool+monoid_1 x = mempty `mappend` x == x+ && x `mappend` mempty == x++-- | The monoid associativity law, 'mappend' must be associative.+--+-- > (x `mappend` y) `mappend` z = x `mappend` (y `mappend` z)+--+monoid_2 :: (Eq a, Data.Monoid.Monoid a) => a -> a -> a -> Bool+monoid_2 x y z = (x `mappend` y) `mappend` z+ == x `mappend` (y `mappend` z)++-- | The 'mconcat' definition. It can be overidden for the sake of effeciency+-- but it must still satisfy the property given by the default definition:+--+-- > mconcat = foldr mappend mempty+--+monoid_3 :: (Eq a, Data.Monoid.Monoid a) => [a] -> Bool+monoid_3 xs = mconcat xs == foldr mappend mempty xs+++-- | First 'Foldable' law+--+-- > Foldable.fold = Foldable.foldr mappend mempty+--+foldable_1 :: (Foldable.Foldable t, Monoid m, Eq m) => t m -> Bool+foldable_1 x = Foldable.fold x == Foldable.foldr mappend mempty x++-- | Second 'Foldable' law+--+-- > foldr f z t = appEndo (foldMap (Endo . f) t) z+--+foldable_2 :: (Foldable.Foldable t, Eq b)+ => (a -> b -> b) -> b -> t a -> Bool+foldable_2 f z t = Foldable.foldr f z t+ == appEndo (Foldable.foldMap (Endo . f) t) z
+ tests/Test/QuickCheck/Utils.hs view
@@ -0,0 +1,29 @@+module Test.QuickCheck.Utils where++import Test.QuickCheck.Gen+++-- | Adjust the size of the generated value.+--+-- In general the size gets bigger and bigger linearly. For some types+-- it is not appropriate to generate ever bigger values but instead+-- to generate lots of intermediate sized values. You could do that using:+--+-- > adjustSize (\n -> min n 5)+--+-- Similarly, for some types the linear size growth may mean getting too big+-- too quickly relative to other values. So you may want to adjust how+-- quickly the size grows. For example dividing by a constant, or even+-- something like the integer square root or log.+--+-- > adjustSize (\n -> n `div` 2)+--+-- Putting this together we can make for example a relatively short list:+--+-- > adjustSize (\n -> min 5 (n `div` 3)) (listOf1 arbitrary)+--+-- Not only do we put a limit on the length but we also scale the growth to+-- prevent it from hitting the maximum size quite so early.+--+adjustSize :: (Int -> Int) -> Gen a -> Gen a+adjustSize adjust gen = sized (\n -> resize (adjust n) gen)
tests/UnitTests.hs view
@@ -2,26 +2,33 @@ ( main ) where -import System.IO (BufferMode(NoBuffering), hSetBuffering, stdout)-import Test.Framework+import Test.Tasty import qualified UnitTests.Distribution.Compat.CreatePipe import qualified UnitTests.Distribution.Compat.ReadP+import qualified UnitTests.Distribution.Simple.Program.Internal+import qualified UnitTests.Distribution.Simple.Utils+import qualified UnitTests.Distribution.System import qualified UnitTests.Distribution.Utils.NubList+import qualified UnitTests.Distribution.Version (versionTests) -tests :: [Test]-tests =- [ testGroup "Distribution.Compat.ReadP"- UnitTests.Distribution.Compat.ReadP.tests- , testGroup "Distribution.Compat.CreatePipe"+tests :: TestTree+tests = testGroup "Unit Tests" $+ [ testGroup "Distribution.Compat.CreatePipe" UnitTests.Distribution.Compat.CreatePipe.tests+ , testGroup "Distribution.Compat.ReadP"+ UnitTests.Distribution.Compat.ReadP.tests+ , testGroup "Distribution.Simple.Program.Internal"+ UnitTests.Distribution.Simple.Program.Internal.tests+ , testGroup "Distribution.Simple.Utils"+ UnitTests.Distribution.Simple.Utils.tests , testGroup "Distribution.Utils.NubList" UnitTests.Distribution.Utils.NubList.tests+ , testGroup "Distribution.System"+ UnitTests.Distribution.System.tests+ , testGroup "Distribution.Version"+ UnitTests.Distribution.Version.versionTests ] main :: IO ()-main = do- -- WORKAROUND: disable buffering on stdout to get streaming test logs- -- test providers _should_ do this themselves- hSetBuffering stdout NoBuffering- defaultMain tests+main = defaultMain tests
tests/UnitTests/Distribution/Compat/CreatePipe.hs view
@@ -2,11 +2,10 @@ import Distribution.Compat.CreatePipe import System.IO (hClose, hGetContents, hPutStr, hSetEncoding, localeEncoding)-import Test.Framework-import Test.Framework.Providers.HUnit-import Test.HUnit hiding (Test)+import Test.Tasty+import Test.Tasty.HUnit -tests :: [Test]+tests :: [TestTree] tests = [testCase "Locale Encoding" case_Locale_Encoding] case_Locale_Encoding :: Assertion
tests/UnitTests/Distribution/Compat/ReadP.hs view
@@ -20,10 +20,10 @@ import Data.List import Distribution.Compat.ReadP-import Test.Framework-import Test.Framework.Providers.QuickCheck2+import Test.Tasty+import Test.Tasty.QuickCheck -tests :: [Test]+tests :: [TestTree] tests = [ testProperty "Get Nil" prop_Get_Nil , testProperty "Get Cons" prop_Get_Cons
+ tests/UnitTests/Distribution/Simple/Program/Internal.hs view
@@ -0,0 +1,36 @@+module UnitTests.Distribution.Simple.Program.Internal+ ( tests+ ) where++import Distribution.Simple.Program.Internal ( stripExtractVersion )++import Test.Tasty+import Test.Tasty.HUnit++v :: String+v = "GNU strip (GNU Binutils; openSUSE 13.2) 2.24.0.20140403-6.1\nCopyright 2013\+ \ Free Software Foundation, Inc.\nThis program is free software; you may\+ \ redistribute it under the terms of\nthe GNU General Public License version 3\+ \ or (at your option) any later version.\nThis program has absolutely no\+ \ warranty.\n"++v' :: String+v' = "GNU strip 2.17.50.0.6-26.el5 20061020"++v'' :: String+v'' = "GNU strip (openSUSE-13.2) 2.23.50.0.6-26.el5 20061020"++v''' :: String+v''' = "GNU strip (GNU (Binutils for) Ubuntu 12.04 ) 2.22"++tests :: [TestTree]+tests =+ [ testCase "Handles parentheses" $+ (stripExtractVersion v) @=? "2.24"+ , testCase "Handles dashes and alphabetic characters" $+ (stripExtractVersion v') @=? "2.17"+ , testCase "Handles single-word parenthetical expressions" $+ (stripExtractVersion v'') @=? "2.23"+ , testCase "Handles nested parentheses" $+ (stripExtractVersion v''') @=? "2.22"+ ]
+ tests/UnitTests/Distribution/Simple/Utils.hs view
@@ -0,0 +1,59 @@+module UnitTests.Distribution.Simple.Utils+ ( tests+ ) where++import Distribution.Simple.Utils+import Distribution.Verbosity++import Data.IORef+import System.Directory ( doesDirectoryExist, doesFileExist+ , getTemporaryDirectory+ , removeDirectoryRecursive, removeFile )+import System.IO (hClose)++import Test.Tasty+import Test.Tasty.HUnit++withTempFileTest :: Assertion+withTempFileTest = do+ fileName <- newIORef ""+ tempDir <- getTemporaryDirectory+ withTempFile tempDir ".foo" $ \fileName' _handle -> do+ writeIORef fileName fileName'+ fileExists <- readIORef fileName >>= doesFileExist+ assertBool "Temporary file not deleted by 'withTempFile'!" (not fileExists)++withTempFileRemovedTest :: Assertion+withTempFileRemovedTest = do+ tempDir <- getTemporaryDirectory+ withTempFile tempDir ".foo" $ \fileName handle -> do+ hClose handle+ removeFile fileName++withTempDirTest :: Assertion+withTempDirTest = do+ dirName <- newIORef ""+ tempDir <- getTemporaryDirectory+ withTempDirectory normal tempDir "foo" $ \dirName' -> do+ writeIORef dirName dirName'+ dirExists <- readIORef dirName >>= doesDirectoryExist+ assertBool "Temporary directory not deleted by 'withTempDirectory'!"+ (not dirExists)++withTempDirRemovedTest :: Assertion+withTempDirRemovedTest = do+ tempDir <- getTemporaryDirectory+ withTempDirectory normal tempDir "foo" $ \dirPath -> do+ removeDirectoryRecursive dirPath++tests :: [TestTree]+tests =+ [ testCase "withTempFile works as expected" $+ withTempFileTest+ , testCase "withTempFile can handle removed files" $+ withTempFileRemovedTest+ , testCase "withTempDirectory works as expected" $+ withTempDirTest+ , testCase "withTempDirectory can handle removed directories" $+ withTempDirRemovedTest+ ]
+ tests/UnitTests/Distribution/System.hs view
@@ -0,0 +1,29 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+module UnitTests.Distribution.System+ ( tests+ ) where++import Control.Monad (liftM2)+import Distribution.Text (Text(..), display, simpleParse)+import Distribution.System+import Test.Tasty+import Test.Tasty.QuickCheck++textRoundtrip :: (Show a, Eq a, Text a) => a -> Property+textRoundtrip x = simpleParse (display x) === Just x++tests :: [TestTree]+tests =+ [ testProperty "Text OS round trip" (textRoundtrip :: OS -> Property)+ , testProperty "Text Arch round trip" (textRoundtrip :: Arch -> Property)+ , testProperty "Text Platform round trip" (textRoundtrip :: Platform -> Property)+ ]++instance Arbitrary OS where+ arbitrary = elements knownOSs++instance Arbitrary Arch where+ arbitrary = elements knownArches++instance Arbitrary Platform where+ arbitrary = liftM2 Platform arbitrary arbitrary
tests/UnitTests/Distribution/Utils/NubList.hs view
@@ -7,12 +7,11 @@ import Data.Monoid #endif import Distribution.Utils.NubList-import Test.Framework-import Test.Framework.Providers.HUnit (testCase)-import Test.Framework.Providers.QuickCheck2-import Test.HUnit (Assertion, assertBool)+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck -tests :: [Test]+tests :: [TestTree] tests = [ testCase "Numlist retains ordering" testOrdering , testCase "Numlist removes duplicates" testDeDupe
+ tests/UnitTests/Distribution/Version.hs view
@@ -0,0 +1,711 @@+{-# OPTIONS_GHC -fno-warn-orphans+ -fno-warn-incomplete-patterns+ -fno-warn-deprecations+ -fno-warn-unused-binds #-} --FIXME+module UnitTests.Distribution.Version (versionTests) where++import Distribution.Version+import Distribution.Text++import Text.PrettyPrint as Disp (text, render, parens, hcat+ ,punctuate, int, char, (<>), (<+>))++import Test.Tasty+import Test.Tasty.QuickCheck+import Test.QuickCheck.Utils+import qualified Test.Laws as Laws++import Control.Monad (liftM, liftM2)+import Data.Maybe (isJust, fromJust)+import Data.List (sort, sortBy, nub)+import Data.Ord (comparing)++versionTests :: [TestTree]+versionTests =+ zipWith (\n p -> testProperty ("Range Property " ++ show n) p) [1::Int ..]+ -- properties to validate the test framework+ [ property prop_nonNull+ , property prop_gen_intervals1+ , property prop_gen_intervals2+--, property prop_equivalentVersionRange --FIXME: runs out of test cases+ , property prop_intermediateVersion++ -- the basic syntactic version range functions+ , property prop_anyVersion+ , property prop_noVersion+ , property prop_thisVersion+ , property prop_notThisVersion+ , property prop_laterVersion+ , property prop_orLaterVersion+ , property prop_earlierVersion+ , property prop_orEarlierVersion+ , property prop_unionVersionRanges+ , property prop_intersectVersionRanges+ , property prop_invertVersionRange+ , property prop_withinVersion+ , property prop_foldVersionRange+ , property prop_foldVersionRange'++ -- the semantic query functions+--, property prop_isAnyVersion1 --FIXME: runs out of test cases+--, property prop_isAnyVersion2 --FIXME: runs out of test cases+--, property prop_isNoVersion --FIXME: runs out of test cases+--, property prop_isSpecificVersion1 --FIXME: runs out of test cases+--, property prop_isSpecificVersion2 --FIXME: runs out of test cases+ , property prop_simplifyVersionRange1+ , property prop_simplifyVersionRange1'+--, property prop_simplifyVersionRange2 --FIXME: runs out of test cases+--, property prop_simplifyVersionRange2' --FIXME: runs out of test cases+--, property prop_simplifyVersionRange2'' --FIXME: actually wrong++ -- converting between version ranges and version intervals+ , property prop_to_intervals+--, property prop_to_intervals_canonical --FIXME: runs out of test cases+--, property prop_to_intervals_canonical' --FIXME: runs out of test cases+ , property prop_from_intervals+ , property prop_to_from_intervals+ , property prop_from_to_intervals+ , property prop_from_to_intervals'++ -- union and intersection of version intervals+ , property prop_unionVersionIntervals+ , property prop_unionVersionIntervals_idempotent+ , property prop_unionVersionIntervals_commutative+ , property prop_unionVersionIntervals_associative+ , property prop_intersectVersionIntervals+ , property prop_intersectVersionIntervals_idempotent+ , property prop_intersectVersionIntervals_commutative+ , property prop_intersectVersionIntervals_associative+ , property prop_union_intersect_distributive+ , property prop_intersect_union_distributive++ -- inversion of version intervals+ , property prop_invertVersionIntervals+ , property prop_invertVersionIntervalsTwice+ ]++-- parseTests :: [TestTree]+-- parseTests =+-- zipWith (\n p -> testProperty ("Parse Property " ++ show n) p) [1::Int ..]+-- -- parsing and pretty printing+-- [ -- property prop_parse_disp1 --FIXME: actually wrong++-- -- These are also wrong, see+-- -- https://github.com/haskell/cabal/issues/3037#issuecomment-177671011++-- -- property prop_parse_disp2+-- -- , property prop_parse_disp3+-- -- , property prop_parse_disp4+-- -- , property prop_parse_disp5+-- ]++instance Arbitrary Version where+ arbitrary = do+ branch <- smallListOf1 $+ frequency [(3, return 0)+ ,(3, return 1)+ ,(2, return 2)+ ,(1, return 3)]+ return (Version branch []) -- deliberate []+ where+ smallListOf1 = adjustSize (\n -> min 5 (n `div` 3)) . listOf1++ shrink (Version branch []) =+ [ Version branch' [] | branch' <- shrink branch, not (null branch') ]+ shrink (Version branch _tags) =+ [ Version branch [] ]++instance Arbitrary VersionRange where+ arbitrary = sized verRangeExp+ where+ verRangeExp n = frequency $+ [ (2, return anyVersion)+ , (1, liftM thisVersion arbitrary)+ , (1, liftM laterVersion arbitrary)+ , (1, liftM orLaterVersion arbitrary)+ , (1, liftM orLaterVersion' arbitrary)+ , (1, liftM earlierVersion arbitrary)+ , (1, liftM orEarlierVersion arbitrary)+ , (1, liftM orEarlierVersion' arbitrary)+ , (1, liftM withinVersion arbitrary)+ , (2, liftM VersionRangeParens arbitrary)+ ] ++ if n == 0 then [] else+ [ (2, liftM2 unionVersionRanges verRangeExp2 verRangeExp2)+ , (2, liftM2 intersectVersionRanges verRangeExp2 verRangeExp2)+ ]+ where+ verRangeExp2 = verRangeExp (n `div` 2)++ orLaterVersion' v =+ unionVersionRanges (LaterVersion v) (ThisVersion v)+ orEarlierVersion' v =+ unionVersionRanges (EarlierVersion v) (ThisVersion v)++---------------------------+-- VersionRange properties+--++prop_nonNull :: Version -> Bool+prop_nonNull = not . null . versionBranch++prop_anyVersion :: Version -> Bool+prop_anyVersion v' =+ withinRange v' anyVersion == True++prop_noVersion :: Version -> Bool+prop_noVersion v' =+ withinRange v' noVersion == False++prop_thisVersion :: Version -> Version -> Bool+prop_thisVersion v v' =+ withinRange v' (thisVersion v)+ == (v' == v)++prop_notThisVersion :: Version -> Version -> Bool+prop_notThisVersion v v' =+ withinRange v' (notThisVersion v)+ == (v' /= v)++prop_laterVersion :: Version -> Version -> Bool+prop_laterVersion v v' =+ withinRange v' (laterVersion v)+ == (v' > v)++prop_orLaterVersion :: Version -> Version -> Bool+prop_orLaterVersion v v' =+ withinRange v' (orLaterVersion v)+ == (v' >= v)++prop_earlierVersion :: Version -> Version -> Bool+prop_earlierVersion v v' =+ withinRange v' (earlierVersion v)+ == (v' < v)++prop_orEarlierVersion :: Version -> Version -> Bool+prop_orEarlierVersion v v' =+ withinRange v' (orEarlierVersion v)+ == (v' <= v)++prop_unionVersionRanges :: VersionRange -> VersionRange -> Version -> Bool+prop_unionVersionRanges vr1 vr2 v' =+ withinRange v' (unionVersionRanges vr1 vr2)+ == (withinRange v' vr1 || withinRange v' vr2)++prop_intersectVersionRanges :: VersionRange -> VersionRange -> Version -> Bool+prop_intersectVersionRanges vr1 vr2 v' =+ withinRange v' (intersectVersionRanges vr1 vr2)+ == (withinRange v' vr1 && withinRange v' vr2)++prop_invertVersionRange :: VersionRange -> Version -> Bool+prop_invertVersionRange vr v' =+ withinRange v' (invertVersionRange vr)+ == not (withinRange v' vr)++prop_withinVersion :: Version -> Version -> Bool+prop_withinVersion v v' =+ withinRange v' (withinVersion v)+ == (v' >= v && v' < upper v)+ where+ upper (Version lower t) = Version (init lower ++ [last lower + 1]) t++prop_foldVersionRange :: VersionRange -> Bool+prop_foldVersionRange range =+ expandWildcard range+ == foldVersionRange anyVersion thisVersion+ laterVersion earlierVersion+ unionVersionRanges intersectVersionRanges+ range+ where+ expandWildcard (WildcardVersion v) =+ intersectVersionRanges (orLaterVersion v) (earlierVersion (upper v))+ where+ upper (Version lower t) = Version (init lower ++ [last lower + 1]) t++ expandWildcard (UnionVersionRanges v1 v2) =+ UnionVersionRanges (expandWildcard v1) (expandWildcard v2)+ expandWildcard (IntersectVersionRanges v1 v2) =+ IntersectVersionRanges (expandWildcard v1) (expandWildcard v2)+ expandWildcard (VersionRangeParens v) = expandWildcard v+ expandWildcard v = v+++prop_foldVersionRange' :: VersionRange -> Bool+prop_foldVersionRange' range =+ canonicalise range+ == foldVersionRange' anyVersion thisVersion+ laterVersion earlierVersion+ orLaterVersion orEarlierVersion+ (\v _ -> withinVersion v)+ unionVersionRanges intersectVersionRanges id+ range+ where+ canonicalise (UnionVersionRanges (LaterVersion v)+ (ThisVersion v')) | v == v'+ = UnionVersionRanges (ThisVersion v')+ (LaterVersion v)+ canonicalise (UnionVersionRanges (EarlierVersion v)+ (ThisVersion v')) | v == v'+ = UnionVersionRanges (ThisVersion v')+ (EarlierVersion v)+ canonicalise (UnionVersionRanges v1 v2) =+ UnionVersionRanges (canonicalise v1) (canonicalise v2)+ canonicalise (IntersectVersionRanges v1 v2) =+ IntersectVersionRanges (canonicalise v1) (canonicalise v2)+ canonicalise (VersionRangeParens v) = canonicalise v+ canonicalise v = v+++prop_isAnyVersion1 :: VersionRange -> Version -> Property+prop_isAnyVersion1 range version =+ isAnyVersion range ==> withinRange version range++prop_isAnyVersion2 :: VersionRange -> Property+prop_isAnyVersion2 range =+ isAnyVersion range ==>+ foldVersionRange True (\_ -> False) (\_ -> False) (\_ -> False)+ (\_ _ -> False) (\_ _ -> False)+ (simplifyVersionRange range)++prop_isNoVersion :: VersionRange -> Version -> Property+prop_isNoVersion range version =+ isNoVersion range ==> not (withinRange version range)++prop_isSpecificVersion1 :: VersionRange -> NonEmptyList Version -> Property+prop_isSpecificVersion1 range (NonEmpty versions) =+ isJust version && not (null versions') ==>+ allEqual (fromJust version : versions')+ where+ version = isSpecificVersion range+ versions' = filter (`withinRange` range) versions+ allEqual xs = and (zipWith (==) xs (tail xs))++prop_isSpecificVersion2 :: VersionRange -> Property+prop_isSpecificVersion2 range =+ isJust version ==>+ foldVersionRange Nothing Just (\_ -> Nothing) (\_ -> Nothing)+ (\_ _ -> Nothing) (\_ _ -> Nothing)+ (simplifyVersionRange range)+ == version++ where+ version = isSpecificVersion range++-- | 'simplifyVersionRange' is a semantic identity on 'VersionRange'.+--+prop_simplifyVersionRange1 :: VersionRange -> Version -> Bool+prop_simplifyVersionRange1 range version =+ withinRange version range == withinRange version (simplifyVersionRange range)++prop_simplifyVersionRange1' :: VersionRange -> Bool+prop_simplifyVersionRange1' range =+ range `equivalentVersionRange` (simplifyVersionRange range)++-- | 'simplifyVersionRange' produces a canonical form for ranges with+-- equivalent semantics.+--+prop_simplifyVersionRange2 :: VersionRange -> VersionRange -> Version -> Property+prop_simplifyVersionRange2 r r' v =+ r /= r' && simplifyVersionRange r == simplifyVersionRange r' ==>+ withinRange v r == withinRange v r'++prop_simplifyVersionRange2' :: VersionRange -> VersionRange -> Property+prop_simplifyVersionRange2' r r' =+ r /= r' && simplifyVersionRange r == simplifyVersionRange r' ==>+ r `equivalentVersionRange` r'++--FIXME: see equivalentVersionRange for details+prop_simplifyVersionRange2'' :: VersionRange -> VersionRange -> Property+prop_simplifyVersionRange2'' r r' =+ r /= r' && r `equivalentVersionRange` r' ==>+ simplifyVersionRange r == simplifyVersionRange r'+ || isNoVersion r+ || isNoVersion r'++--------------------+-- VersionIntervals+--++-- | Generating VersionIntervals+--+-- This is a tad tricky as VersionIntervals is an abstract type, so we first+-- make a local type for generating the internal representation. Then we check+-- that this lets us construct valid 'VersionIntervals'.+--+newtype VersionIntervals' = VersionIntervals' [VersionInterval]+ deriving (Eq, Show)++instance Arbitrary VersionIntervals' where+ arbitrary = do+ ubound <- arbitrary+ bounds <- arbitrary+ let intervals = mergeTouching+ . map fixEmpty+ . replaceUpper ubound+ . pairs+ . sortBy (comparing fst)+ $ bounds+ return (VersionIntervals' intervals)++ where+ pairs ((l, lb):(u, ub):bs) = (LowerBound l lb, UpperBound u ub)+ : pairs bs+ pairs _ = []++ replaceUpper NoUpperBound [(l,_)] = [(l, NoUpperBound)]+ replaceUpper NoUpperBound (i:is) = i : replaceUpper NoUpperBound is+ replaceUpper _ is = is++ -- merge adjacent intervals that touch+ mergeTouching (i1@(l,u):i2@(l',u'):is)+ | doesNotTouch u l' = i1 : mergeTouching (i2:is)+ | otherwise = mergeTouching ((l,u'):is)+ mergeTouching is = is++ doesNotTouch :: UpperBound -> LowerBound -> Bool+ doesNotTouch NoUpperBound _ = False+ doesNotTouch (UpperBound u ub) (LowerBound l lb) =+ u < l+ || (u == l && ub == ExclusiveBound && lb == ExclusiveBound)++ fixEmpty (LowerBound l _, UpperBound u _)+ | l == u = (LowerBound l InclusiveBound, UpperBound u InclusiveBound)+ fixEmpty i = i++ shrink (VersionIntervals' intervals) =+ [ VersionIntervals' intervals' | intervals' <- shrink intervals ]++instance Arbitrary Bound where+ arbitrary = elements [ExclusiveBound, InclusiveBound]++instance Arbitrary LowerBound where+ arbitrary = liftM2 LowerBound arbitrary arbitrary++instance Arbitrary UpperBound where+ arbitrary = oneof [return NoUpperBound+ ,liftM2 UpperBound arbitrary arbitrary]++-- | Check that our VersionIntervals' arbitrary instance generates intervals+-- that satisfies the invariant.+--+prop_gen_intervals1 :: VersionIntervals' -> Bool+prop_gen_intervals1 (VersionIntervals' intervals) =+ isJust (mkVersionIntervals intervals)++instance Arbitrary VersionIntervals where+ arbitrary = do+ VersionIntervals' intervals <- arbitrary+ case mkVersionIntervals intervals of+ Just xs -> return xs++-- | Check that constructing our intervals type and converting it to a+-- 'VersionRange' and then into the true intervals type gives us back+-- the exact same sequence of intervals. This tells us that our arbitrary+-- instance for 'VersionIntervals'' is ok.+--+prop_gen_intervals2 :: VersionIntervals' -> Bool+prop_gen_intervals2 (VersionIntervals' intervals') =+ asVersionIntervals (fromVersionIntervals intervals) == intervals'+ where+ Just intervals = mkVersionIntervals intervals'++-- | Check that 'VersionIntervals' models 'VersionRange' via+-- 'toVersionIntervals'.+--+prop_to_intervals :: VersionRange -> Version -> Bool+prop_to_intervals range version =+ withinRange version range == withinIntervals version intervals+ where+ intervals = toVersionIntervals range++-- | Check that semantic equality on 'VersionRange's is the same as converting+-- to 'VersionIntervals' and doing syntactic equality.+--+prop_to_intervals_canonical :: VersionRange -> VersionRange -> Property+prop_to_intervals_canonical r r' =+ r /= r' && r `equivalentVersionRange` r' ==>+ toVersionIntervals r == toVersionIntervals r'++prop_to_intervals_canonical' :: VersionRange -> VersionRange -> Property+prop_to_intervals_canonical' r r' =+ r /= r' && toVersionIntervals r == toVersionIntervals r' ==>+ r `equivalentVersionRange` r'++-- | Check that 'VersionIntervals' models 'VersionRange' via+-- 'fromVersionIntervals'.+--+prop_from_intervals :: VersionIntervals -> Version -> Bool+prop_from_intervals intervals version =+ withinRange version range == withinIntervals version intervals+ where+ range = fromVersionIntervals intervals++-- | @'toVersionIntervals' . 'fromVersionIntervals'@ is an exact identity on+-- 'VersionIntervals'.+--+prop_to_from_intervals :: VersionIntervals -> Bool+prop_to_from_intervals intervals =+ toVersionIntervals (fromVersionIntervals intervals) == intervals++-- | @'fromVersionIntervals' . 'toVersionIntervals'@ is a semantic identity on+-- 'VersionRange', though not necessarily a syntactic identity.+--+prop_from_to_intervals :: VersionRange -> Bool+prop_from_to_intervals range =+ range' `equivalentVersionRange` range+ where+ range' = fromVersionIntervals (toVersionIntervals range)++-- | Equivalent of 'prop_from_to_intervals'+--+prop_from_to_intervals' :: VersionRange -> Version -> Bool+prop_from_to_intervals' range version =+ withinRange version range' == withinRange version range+ where+ range' = fromVersionIntervals (toVersionIntervals range)++-- | The semantics of 'unionVersionIntervals' is (||).+--+prop_unionVersionIntervals :: VersionIntervals -> VersionIntervals+ -> Version -> Bool+prop_unionVersionIntervals is1 is2 v =+ withinIntervals v (unionVersionIntervals is1 is2)+ == (withinIntervals v is1 || withinIntervals v is2)++-- | 'unionVersionIntervals' is idempotent+--+prop_unionVersionIntervals_idempotent :: VersionIntervals -> Bool+prop_unionVersionIntervals_idempotent =+ Laws.idempotent_binary unionVersionIntervals++-- | 'unionVersionIntervals' is commutative+--+prop_unionVersionIntervals_commutative :: VersionIntervals+ -> VersionIntervals -> Bool+prop_unionVersionIntervals_commutative =+ Laws.commutative unionVersionIntervals++-- | 'unionVersionIntervals' is associative+--+prop_unionVersionIntervals_associative :: VersionIntervals+ -> VersionIntervals+ -> VersionIntervals -> Bool+prop_unionVersionIntervals_associative =+ Laws.associative unionVersionIntervals++-- | The semantics of 'intersectVersionIntervals' is (&&).+--+prop_intersectVersionIntervals :: VersionIntervals -> VersionIntervals+ -> Version -> Bool+prop_intersectVersionIntervals is1 is2 v =+ withinIntervals v (intersectVersionIntervals is1 is2)+ == (withinIntervals v is1 && withinIntervals v is2)++-- | 'intersectVersionIntervals' is idempotent+--+prop_intersectVersionIntervals_idempotent :: VersionIntervals -> Bool+prop_intersectVersionIntervals_idempotent =+ Laws.idempotent_binary intersectVersionIntervals++-- | 'intersectVersionIntervals' is commutative+--+prop_intersectVersionIntervals_commutative :: VersionIntervals+ -> VersionIntervals -> Bool+prop_intersectVersionIntervals_commutative =+ Laws.commutative intersectVersionIntervals++-- | 'intersectVersionIntervals' is associative+--+prop_intersectVersionIntervals_associative :: VersionIntervals+ -> VersionIntervals+ -> VersionIntervals -> Bool+prop_intersectVersionIntervals_associative =+ Laws.associative intersectVersionIntervals++-- | 'unionVersionIntervals' distributes over 'intersectVersionIntervals'+--+prop_union_intersect_distributive :: Property+prop_union_intersect_distributive =+ Laws.distributive_left unionVersionIntervals intersectVersionIntervals+ .&. Laws.distributive_right unionVersionIntervals intersectVersionIntervals++-- | 'intersectVersionIntervals' distributes over 'unionVersionIntervals'+--+prop_intersect_union_distributive :: Property+prop_intersect_union_distributive =+ Laws.distributive_left intersectVersionIntervals unionVersionIntervals+ .&. Laws.distributive_right intersectVersionIntervals unionVersionIntervals++-- | The semantics of 'invertVersionIntervals' is 'not'.+--+prop_invertVersionIntervals :: VersionIntervals+ -> Version -> Bool+prop_invertVersionIntervals vi v =+ withinIntervals v (invertVersionIntervals vi)+ == not (withinIntervals v vi)++-- | Double application of 'invertVersionIntervals' is the identity function+prop_invertVersionIntervalsTwice :: VersionIntervals -> Bool+prop_invertVersionIntervalsTwice vi =+ invertVersionIntervals (invertVersionIntervals vi) == vi++++--------------------------------+-- equivalentVersionRange helper++prop_equivalentVersionRange :: VersionRange -> VersionRange+ -> Version -> Property+prop_equivalentVersionRange range range' version =+ equivalentVersionRange range range' && range /= range' ==>+ withinRange version range == withinRange version range'++--FIXME: this is wrong. consider version ranges "<=1" and "<1.0"+-- this algorithm cannot distinguish them because there is no version+-- that is included by one that is excluded by the other.+-- Alternatively we must reconsider the semantics of '<' and '<='+-- in version ranges / version intervals. Perhaps the canonical+-- representation should use just < v and interpret "<= v" as "< v.0".+equivalentVersionRange :: VersionRange -> VersionRange -> Bool+equivalentVersionRange vr1 vr2 =+ let allVersionsUsed = nub (sort (versionsUsed vr1 ++ versionsUsed vr2))+ minPoint = Version [0] []+ maxPoint | null allVersionsUsed = minPoint+ | otherwise = case maximum allVersionsUsed of+ Version vs _ -> Version (vs ++ [1]) []+ probeVersions = minPoint : maxPoint+ : intermediateVersions allVersionsUsed++ in all (\v -> withinRange v vr1 == withinRange v vr2) probeVersions++ where+ versionsUsed = foldVersionRange [] (\x->[x]) (\x->[x]) (\x->[x]) (++) (++)+ intermediateVersions (v1:v2:vs) = v1 : intermediateVersion v1 v2+ : intermediateVersions (v2:vs)+ intermediateVersions vs = vs++intermediateVersion :: Version -> Version -> Version+intermediateVersion v1 v2 | v1 >= v2 = error "intermediateVersion: v1 >= v2"+intermediateVersion (Version v1 _) (Version v2 _) =+ Version (intermediateList v1 v2) []+ where+ intermediateList :: [Int] -> [Int] -> [Int]+ intermediateList [] (_:_) = [0]+ intermediateList (x:xs) (y:ys)+ | x < y = x : xs ++ [0]+ | otherwise = x : intermediateList xs ys++prop_intermediateVersion :: Version -> Version -> Property+prop_intermediateVersion v1 v2 =+ (v1 /= v2) && not (adjacentVersions v1 v2) ==>+ if v1 < v2+ then let v = intermediateVersion v1 v2+ in (v1 < v && v < v2)+ else let v = intermediateVersion v2 v1+ in v1 > v && v > v2++adjacentVersions :: Version -> Version -> Bool+adjacentVersions (Version v1 _) (Version v2 _) = v1 ++ [0] == v2+ || v2 ++ [0] == v1++--------------------------------+-- Parsing and pretty printing+--++prop_parse_disp1 :: VersionRange -> Bool+prop_parse_disp1 vr =+ fmap stripParens (simpleParse (display vr)) == Just (canonicalise vr)++ where+ canonicalise = swizzle . swap++ swizzle (UnionVersionRanges (UnionVersionRanges v1 v2) v3)+ | not (isOrLaterVersion v1 v2) && not (isOrEarlierVersion v1 v2)+ = swizzle (UnionVersionRanges v1 (UnionVersionRanges v2 v3))++ swizzle (IntersectVersionRanges (IntersectVersionRanges v1 v2) v3)+ = swizzle (IntersectVersionRanges v1 (IntersectVersionRanges v2 v3))++ swizzle (UnionVersionRanges v1 v2) =+ UnionVersionRanges (swizzle v1) (swizzle v2)+ swizzle (IntersectVersionRanges v1 v2) =+ IntersectVersionRanges (swizzle v1) (swizzle v2)+ swizzle (VersionRangeParens v) = swizzle v+ swizzle v = v++ isOrLaterVersion (ThisVersion v) (LaterVersion v') = v == v'+ isOrLaterVersion _ _ = False++ isOrEarlierVersion (ThisVersion v) (EarlierVersion v') = v == v'+ isOrEarlierVersion _ _ = False++ swap =+ foldVersionRange' anyVersion thisVersion+ laterVersion earlierVersion+ orLaterVersion orEarlierVersion+ (\v _ -> withinVersion v)+ unionVersionRanges intersectVersionRanges id++ stripParens :: VersionRange -> VersionRange+ stripParens (VersionRangeParens v) = stripParens v+ stripParens (UnionVersionRanges v1 v2) =+ UnionVersionRanges (stripParens v1) (stripParens v2)+ stripParens (IntersectVersionRanges v1 v2) =+ IntersectVersionRanges (stripParens v1) (stripParens v2)+ stripParens v = v++prop_parse_disp2 :: VersionRange -> Property+prop_parse_disp2 vr =+ let b = fmap (display :: VersionRange -> String) (simpleParse (display vr))+ a = Just (display vr)+ in+ counterexample ("Expected: " ++ show a) $+ counterexample ("But got: " ++ show b) $+ b == a++prop_parse_disp3 :: VersionRange -> Property+prop_parse_disp3 vr =+ let a = Just (display vr)+ b = fmap displayRaw (simpleParse (display vr))+ in+ counterexample ("Expected: " ++ show a) $+ counterexample ("But got: " ++ show b) $+ b == a++prop_parse_disp4 :: VersionRange -> Property+prop_parse_disp4 vr =+ let a = Just vr+ b = (simpleParse (display vr))+ in+ counterexample ("Expected: " ++ show a) $+ counterexample ("But got: " ++ show b) $+ b == a++prop_parse_disp5 :: VersionRange -> Property+prop_parse_disp5 vr =+ let a = Just vr+ b = simpleParse (displayRaw vr)+ in+ counterexample ("Expected: " ++ show a) $+ counterexample ("But got: " ++ show b) $+ b == a++displayRaw :: VersionRange -> String+displayRaw =+ Disp.render+ . foldVersionRange' -- precedence:+ -- All the same as the usual pretty printer, except for the parens+ ( Disp.text "-any")+ (\v -> Disp.text "==" <> disp v)+ (\v -> Disp.char '>' <> disp v)+ (\v -> Disp.char '<' <> disp v)+ (\v -> Disp.text ">=" <> disp v)+ (\v -> Disp.text "<=" <> disp v)+ (\v _ -> Disp.text "==" <> dispWild v)+ (\r1 r2 -> r1 <+> Disp.text "||" <+> r2)+ (\r1 r2 -> r1 <+> Disp.text "&&" <+> r2)+ (\r -> Disp.parens r) -- parens++ where+ dispWild (Version b _) =+ Disp.hcat (Disp.punctuate (Disp.char '.') (map Disp.int b))+ <> Disp.text ".*"